Version 8 #43

Merged
danieljsummers merged 37 commits from version-8 into main 2022-08-19 19:08:31 +00:00
9 changed files with 75 additions and 19 deletions
Showing only changes of commit ae29a6c03b - Show all commits

View File

@ -312,6 +312,13 @@ type ListPreferences =
/// How the as-of date should be automatically displayed /// How the as-of date should be automatically displayed
AsOfDateDisplay : AsOfDateDisplay 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 /// Functions to support list preferences
module ListPreferences = module ListPreferences =
@ -323,8 +330,8 @@ module ListPreferences =
DaysToKeepNew = 7 DaysToKeepNew = 7
LongTermUpdateWeeks = 4 LongTermUpdateWeeks = 4
EmailFromName = "PrayerTracker" EmailFromName = "PrayerTracker"
EmailFromAddress = "prayer@djs-consulting.com" EmailFromAddress = "prayer@bitbadger.solutions"
Fonts = "Century Gothic,Tahoma,Luxi Sans,sans-serif" Fonts = "native"
HeadingColor = "maroon" HeadingColor = "maroon"
LineColor = "navy" LineColor = "navy"
HeadingFontSize = 16 HeadingFontSize = 16

View File

@ -98,6 +98,15 @@ let expirationTests =
[<Tests>] [<Tests>]
let listPreferencesTests = let listPreferencesTests =
testList "ListPreferences" [ 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" { test "empty is as expected" {
let mt = ListPreferences.empty let mt = ListPreferences.empty
Expect.equal mt.SmallGroupId.Value Guid.Empty "The small group ID should have been an empty GUID" 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.EmailFromName "PrayerTracker" "The default e-mail from name should have been PrayerTracker"
Expect.equal mt.EmailFromAddress "prayer@djs-consulting.com" Expect.equal mt.EmailFromAddress "prayer@djs-consulting.com"
"The default e-mail from address should have been 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.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.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" Expect.equal mt.HeadingFontSize 16 "The default heading font size should have been 16"

View File

@ -78,6 +78,28 @@ let namedColorList name selected attrs (s : IStringLocalizer) =
|> List.ofSeq |> List.ofSeq
|> select (_name name :: attrs) |> 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 /// Generate an input[type=radio] that is selected if its value is the current value
let radio name domId value current = let radio name domId value current =
input [ _type "radio" input [ _type "radio"

View File

@ -1,6 +1,6 @@
module PrayerTracker.Views.PrayerRequest module PrayerTracker.Views.PrayerRequest
open System open System.Globalization
open System.IO open System.IO
open Giraffe open Giraffe
open Giraffe.ViewEngine open Giraffe.ViewEngine
@ -17,7 +17,11 @@ let edit (model : EditRequest) today ctx viewInfo =
let s = I18N.localizer.Force () let s = I18N.localizer.Force ()
let pageTitle = if model.IsNew then "Add a New Request" else "Edit Request" let pageTitle = if model.IsNew then "Add a New Request" else "Edit Request"
let vi = AppViewInfo.withOnLoadScript "PT.initCKEditor" viewInfo 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 csrfToken ctx
inputField "hidden" (nameof model.RequestId) model.RequestId [] inputField "hidden" (nameof model.RequestId) model.RequestId []
div [ _fieldRow ] [ div [ _fieldRow ] [
@ -79,7 +83,7 @@ let email model viewInfo =
let pageTitle = $"""{s["Prayer Requests"].Value} {model.SmallGroup.Name}""" let pageTitle = $"""{s["Prayer Requests"].Value} {model.SmallGroup.Name}"""
let prefs = model.SmallGroup.Preferences let prefs = model.SmallGroup.Preferences
let addresses = model.Recipients |> List.map (fun mbr -> $"{mbr.Name} <{mbr.Email}>") |> String.concat ", " 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"] locStr s["The request list was sent to the following people, via individual e-mails"]
rawText ":" rawText ":"
br [] br []
@ -202,7 +206,7 @@ let maintain (model : MaintainRequests) (ctx : HttpContext) viewInfo =
] ]
] ]
div [ updateClass ] [ 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 [ _class "cell" ] [ locStr types[req.RequestType] ]
div [ expiredClass ] [ str (match req.Requestor with Some r -> r | None -> " ") ] div [ expiredClass ] [ str (match req.Requestor with Some r -> r | None -> " ") ]
@ -300,7 +304,7 @@ let print model version =
rawText (model.AsHtml s) rawText (model.AsHtml s)
br [] br []
hr [] 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""" img [ _src $"""/img/{s["footer_en"].Value}.png"""
_style "vertical-align:text-bottom;" _style "vertical-align:text-bottom;"
_alt imgAlt _alt imgAlt
@ -317,7 +321,7 @@ let view model viewInfo =
let s = I18N.localizer.Force () let s = I18N.localizer.Force ()
let pageTitle = $"""{s["Prayer Requests"].Value} {model.SmallGroup.Name}""" let pageTitle = $"""{s["Prayer Requests"].Value} {model.SmallGroup.Name}"""
let spacer = rawText " &nbsp; &nbsp; &nbsp; " let spacer = rawText " &nbsp; &nbsp; &nbsp; "
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" ] [ [ div [ _class "pt-center-text" ] [
br [] br []
a [ _class "pt-icon-link" 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) if date.DayOfWeek = IsoDayOfWeek.Sunday then date else findSunday (date.PlusDays 1)
let sunday = findSunday model.Date let sunday = findSunday model.Date
a [ _class "pt-icon-link" 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 ] [ _title s["List for Next Sunday"].Value ] [
icon "update"; rawText " &nbsp;"; locStr s["List for Next Sunday"] icon "update"; rawText " &nbsp;"; locStr s["List for Next Sunday"]
] ]

View File

@ -14,7 +14,11 @@ let announcement isAdmin ctx viewInfo =
let model = { SendToClass = ""; Text = ""; AddToRequestList = None; RequestType = None } let model = { SendToClass = ""; Text = ""; AddToRequestList = None; RequestType = None }
let reqTypes = ReferenceList.requestTypeList s let reqTypes = ReferenceList.requestTypeList s
let vi = AppViewInfo.withOnLoadScript "PT.smallGroup.announcement.onPageLoad" viewInfo 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 csrfToken ctx
div [ _fieldRow ] [ div [ _fieldRow ] [
div [ _inputFieldWith [ "pt-editor" ] ] [ div [ _inputFieldWith [ "pt-editor" ] ] [
@ -461,7 +465,7 @@ let preferences (model : EditPreferences) ctx viewInfo =
input [ _type "color" input [ _type "color"
_name (nameof model.LineColor) _name (nameof model.LineColor)
_id $"{nameof model.LineColor}_Color" _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 ] if not (model.LineColor.StartsWith "#") then _disabled ]
] ]
] ]
@ -483,7 +487,7 @@ let preferences (model : EditPreferences) ctx viewInfo =
input [ _type "color" input [ _type "color"
_name (nameof model.HeadingColor) _name (nameof model.HeadingColor)
_id $"{nameof model.HeadingColor}_Color" _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 ] if not (model.HeadingColor.StartsWith "#") then _disabled ]
] ]
] ]

View File

@ -778,7 +778,7 @@ with
let p = this.SmallGroup.Preferences let p = this.SmallGroup.Preferences
let asOfSize = Math.Round (float p.TextFontSize * 0.8, 2) let asOfSize = Math.Round (float p.TextFontSize * 0.8, 2)
[ if this.ShowHeader then [ 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;" ] [ span [ _style $"font-size:%i{p.HeadingFontSize}pt;" ] [
strong [] [ str s["Prayer Requests"].Value ] strong [] [ str s["Prayer Requests"].Value ]
] ]
@ -792,7 +792,7 @@ with
br [] br []
for _, name, reqs in this.RequestsByType s do for _, name, reqs in this.RequestsByType s do
div [ _style "padding-left:10px;padding-bottom:.5em;" ] [ 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 [] [ 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;" ] [ 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 "&nbsp; &nbsp; "; str name.Value; rawText "&nbsp; &nbsp; " rawText "&nbsp; &nbsp; "; str name.Value; rawText "&nbsp; &nbsp; "
@ -804,7 +804,7 @@ with
reqs reqs
|> List.map (fun req -> |> List.map (fun req ->
let bullet = if this.IsNew req then "circle" else "disc" 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 match req.Requestor with
| Some r when r <> "" -> | Some r when r <> "" ->
strong [] [ str r ] strong [] [ str r ]

View File

@ -260,7 +260,7 @@ let sendAnnouncement : HttpHandler = requireAccess [ User ] >=> validateCsrf >=>
// Reformat the text to use the class's font stylings // Reformat the text to use the class's font stylings
let requestText = ckEditorToText model.Text let requestText = ckEditorToText model.Text
let htmlText = 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 |> renderHtmlNode
let plainText = (htmlToPlainText >> wordWrap 74) htmlText let plainText = (htmlToPlainText >> wordWrap 74) htmlText
// Send the e-mails // Send the e-mails

View File

@ -86,9 +86,17 @@ this.PT = {
initCKEditor() { initCKEditor() {
ClassicEditor ClassicEditor
.create(document.querySelector("#Text")) .create(document.querySelector("#Text"))
.then(editor => window.ckEditor = editor)
.catch(console.error) .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 * Scripts for pages served by the Church controller
*/ */

View File

@ -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 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 "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_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 TABLE pt."ListPreference" RENAME TO list_preference;
ALTER INDEX pt."IX_ListPreference_TimeZoneId" RENAME TO ix_list_preference_time_zone_id; 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 -- Small Group Member
ALTER TABLE pt."Member" RENAME COLUMN "MemberId" TO id; ALTER TABLE pt."Member" RENAME COLUMN "MemberId" TO id;
ALTER TABLE pt."Member" RENAME COLUMN "SmallGroupId" TO small_group_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; ALTER INDEX pt."IX_SmallGroup_ChurchId" RENAME TO ix_small_group_church_id;
-- Time Zone (goes away) -- Time Zone (goes away)
ALTER TABLE pt.list_preference DROP CONSTRAINT fk_list_preference_time_zone_id;
DROP TABLE pt."TimeZone"; DROP TABLE pt."TimeZone";
-- User -- User