Version 8 #43
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
open Giraffe.ViewEngine
|
open Giraffe.ViewEngine
|
||||||
open Giraffe.ViewEngine.Accessibility
|
open Giraffe.ViewEngine.Accessibility
|
||||||
|
open Giraffe.ViewEngine.Htmx
|
||||||
open PrayerTracker
|
open PrayerTracker
|
||||||
open PrayerTracker.Entities
|
open PrayerTracker.Entities
|
||||||
open PrayerTracker.ViewModels
|
open PrayerTracker.ViewModels
|
||||||
|
@ -58,71 +59,49 @@ let edit (model : EditChurch) ctx viewInfo =
|
||||||
|
|
||||||
/// View for church maintenance page
|
/// View for church maintenance page
|
||||||
let maintain (churches : Church list) (stats : Map<string, ChurchStats>) ctx viewInfo =
|
let maintain (churches : Church list) (stats : Map<string, ChurchStats>) ctx viewInfo =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let vi =
|
let vi = AppViewInfo.withScopedStyles [ "#churchList { grid-template-columns: repeat(7, auto); }" ] viewInfo
|
||||||
AppViewInfo.withScopedStyles [
|
let churchTable =
|
||||||
"#churchList { grid-template-columns: repeat(7, auto); }"
|
|
||||||
] viewInfo
|
|
||||||
let chTbl =
|
|
||||||
match churches with
|
match churches with
|
||||||
| [] -> space
|
| [] -> space
|
||||||
| _ ->
|
| _ ->
|
||||||
section [ _id "churchList"; _class "pt-data-list"; _ariaLabel "Church list" ] [
|
section [ _id "churchList"; _class "pt-table"; _ariaLabel "Church list" ] [
|
||||||
header [] [ locStr s["Actions"] ]
|
div [ _class "row head" ] [
|
||||||
header [] [ locStr s["Name"] ]
|
header [ _class "cell" ] [ locStr s["Actions"] ]
|
||||||
header [] [ locStr s["Location"] ]
|
header [ _class "cell" ] [ locStr s["Name"] ]
|
||||||
header [] [ locStr s["Groups"] ]
|
header [ _class "cell" ] [ locStr s["Location"] ]
|
||||||
header [] [ locStr s["Requests"] ]
|
header [ _class "cell" ] [ locStr s["Groups"] ]
|
||||||
header [] [ locStr s["Users"] ]
|
header [ _class "cell" ] [ locStr s["Requests"] ]
|
||||||
header [] [ locStr s["Interface?"] ]
|
header [ _class "cell" ] [ locStr s["Users"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Interface?"] ]
|
||||||
|
]
|
||||||
for church in churches do
|
for church in churches do
|
||||||
let churchId = shortGuid church.Id.Value
|
let churchId = shortGuid church.Id.Value
|
||||||
let delAction = $"/church/{churchId}/delete"
|
let delAction = $"/church/{churchId}/delete"
|
||||||
let delPrompt = s["Are you sure you want to delete this {0}? This action cannot be undone.",
|
let delPrompt = s["Are you sure you want to delete this {0}? This action cannot be undone.",
|
||||||
$"""{s["Church"].Value.ToLower ()} ({church.Name})"""]
|
$"""{s["Church"].Value.ToLower ()} ({church.Name})"""]
|
||||||
div [ _class "row" ] [
|
div [ _class "row" ] [
|
||||||
div [] [
|
div [ _class "cell actions" ] [
|
||||||
a [ _href $"/church/{churchId}/edit"; _title s["Edit This Church"].Value ] [ icon "edit" ]
|
a [ _href $"/church/{churchId}/edit"; _title s["Edit This Church"].Value ] [
|
||||||
a [ _href delAction
|
iconSized 18 "edit"
|
||||||
_title s["Delete This Church"].Value
|
]
|
||||||
_onclick $"return PT.confirmDelete('{delAction}','{delPrompt}')" ] [
|
a [ _href delAction
|
||||||
icon "delete_forever"
|
_title s["Delete This Church"].Value
|
||||||
|
_hxPost delAction
|
||||||
|
_hxConfirm delPrompt.Value ] [
|
||||||
|
iconSized 18 "delete_forever"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
div [] [ str church.Name ]
|
div [ _class "cell" ] [ str church.Name ]
|
||||||
div [] [ str church.City; rawText ", "; str church.State ]
|
div [ _class "cell" ] [ str church.City; rawText ", "; str church.State ]
|
||||||
div [ _class "pt-right-text" ] [ rawText (stats[churchId].SmallGroups.ToString "N0") ]
|
div [ _class "cell pt-right-text" ] [ rawText (stats[churchId].SmallGroups.ToString "N0") ]
|
||||||
div [ _class "pt-right-text" ] [ rawText (stats[churchId].PrayerRequests.ToString "N0") ]
|
div [ _class "cell pt-right-text" ] [ rawText (stats[churchId].PrayerRequests.ToString "N0") ]
|
||||||
div [ _class "pt-right-text" ] [ rawText (stats[churchId].Users.ToString "N0") ]
|
div [ _class "cell pt-right-text" ] [ rawText (stats[churchId].Users.ToString "N0") ]
|
||||||
div [ _class "pt-center-text" ] [ locStr s[if church.HasVpsInterface then "Yes" else "No"] ]
|
div [ _class "cell pt-center-text" ] [
|
||||||
|
locStr s[if church.HasVpsInterface then "Yes" else "No"]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
// table [ _class "pt-table pt-action-table" ] [
|
|
||||||
// tableHeadings s [ "Actions"; "Name"; "Location"; "Groups"; "Requests"; "Users"; "Interface?" ]
|
|
||||||
// churches
|
|
||||||
// |> List.map (fun ch ->
|
|
||||||
// let chId = shortGuid ch.Id.Value
|
|
||||||
// let delAction = $"/church/{chId}/delete"
|
|
||||||
// let delPrompt = s["Are you sure you want to delete this {0}? This action cannot be undone.",
|
|
||||||
// $"""{s["Church"].Value.ToLower ()} ({ch.Name})"""]
|
|
||||||
// tr [] [
|
|
||||||
// td [] [
|
|
||||||
// a [ _href $"/church/{chId}/edit"; _title s["Edit This Church"].Value ] [ icon "edit" ]
|
|
||||||
// a [ _href delAction
|
|
||||||
// _title s["Delete This Church"].Value
|
|
||||||
// _onclick $"return PT.confirmDelete('{delAction}','{delPrompt}')" ] [
|
|
||||||
// icon "delete_forever"
|
|
||||||
// ]
|
|
||||||
// ]
|
|
||||||
// td [] [ str ch.Name ]
|
|
||||||
// td [] [ str ch.City; rawText ", "; str ch.State ]
|
|
||||||
// td [ _class "pt-right-text" ] [ rawText (stats[chId].SmallGroups.ToString "N0") ]
|
|
||||||
// td [ _class "pt-right-text" ] [ rawText (stats[chId].PrayerRequests.ToString "N0") ]
|
|
||||||
// td [ _class "pt-right-text" ] [ rawText (stats[chId].Users.ToString "N0") ]
|
|
||||||
// td [ _class "pt-center-text" ] [ locStr s[if ch.HasVpsInterface then "Yes" else "No"] ]
|
|
||||||
// ])
|
|
||||||
// |> tbody []
|
|
||||||
// ]
|
|
||||||
[ div [ _class "pt-center-text" ] [
|
[ div [ _class "pt-center-text" ] [
|
||||||
br []
|
br []
|
||||||
a [ _href $"/church/{emptyGuid}/edit"; _title s["Add a New Church"].Value ] [
|
a [ _href $"/church/{emptyGuid}/edit"; _title s["Add a New Church"].Value ] [
|
||||||
|
@ -132,8 +111,10 @@ let maintain (churches : Church list) (stats : Map<string, ChurchStats>) ctx vie
|
||||||
br []
|
br []
|
||||||
]
|
]
|
||||||
tableSummary churches.Length s
|
tableSummary churches.Length s
|
||||||
chTbl
|
form [ _method "post" ] [
|
||||||
form [ _id "DeleteForm"; _action ""; _method "post" ] [ csrfToken ctx ]
|
csrfToken ctx
|
||||||
|
churchTable
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|> Layout.Content.wide
|
|> Layout.Content.wide
|
||||||
|> Layout.standard vi "Maintain Churches"
|
|> Layout.standard vi "Maintain Churches"
|
||||||
|
|
|
@ -141,15 +141,15 @@ module Navigation =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
header [ _id "pt-language"; Target.body ] [
|
header [ _id "pt-language"; Target.body ] [
|
||||||
div [] [
|
div [] [
|
||||||
span [ _class "u" ] [ locStr s["Language"]; rawText ": " ]
|
span [ _title s["Language"].Value ] [ icon "record_voice_over"; space ]
|
||||||
match langCode () with
|
match langCode () with
|
||||||
| "es" ->
|
| "es" ->
|
||||||
locStr s["Spanish"]
|
strong [] [ locStr s["Spanish"] ]
|
||||||
rawText " • "
|
rawText " "
|
||||||
a [ _href "/language/en" ] [ locStr s["Change to English"] ]
|
a [ _href "/language/en" ] [ locStr s["Change to English"] ]
|
||||||
| _ ->
|
| _ ->
|
||||||
locStr s["English"]
|
strong [] [ locStr s["English"] ]
|
||||||
rawText " • "
|
rawText " "
|
||||||
a [ _href "/language/es" ] [ locStr s["Cambie a Español"] ]
|
a [ _href "/language/es" ] [ locStr s["Cambie a Español"] ]
|
||||||
]
|
]
|
||||||
match m.Group with
|
match m.Group with
|
||||||
|
|
|
@ -4,6 +4,8 @@ open System
|
||||||
open System.IO
|
open System.IO
|
||||||
open Giraffe
|
open Giraffe
|
||||||
open Giraffe.ViewEngine
|
open Giraffe.ViewEngine
|
||||||
|
open Giraffe.ViewEngine.Accessibility
|
||||||
|
open Giraffe.ViewEngine.Htmx
|
||||||
open Microsoft.AspNetCore.Http
|
open Microsoft.AspNetCore.Http
|
||||||
open NodaTime
|
open NodaTime
|
||||||
open PrayerTracker
|
open PrayerTracker
|
||||||
|
@ -156,10 +158,11 @@ let maintain (model : MaintainRequests) (ctx : HttpContext) viewInfo =
|
||||||
let prefs = model.SmallGroup.Preferences
|
let prefs = model.SmallGroup.Preferences
|
||||||
let types = ReferenceList.requestTypeList s |> Map.ofList
|
let types = ReferenceList.requestTypeList s |> Map.ofList
|
||||||
let updReq (req : PrayerRequest) =
|
let updReq (req : PrayerRequest) =
|
||||||
if req.UpdateRequired now prefs.DaysToExpire prefs.LongTermUpdateWeeks then "pt-request-update" else ""
|
if req.UpdateRequired now prefs.DaysToExpire prefs.LongTermUpdateWeeks then "cell pt-request-update" else "cell"
|
||||||
|> _class
|
|> _class
|
||||||
let reqExp (req : PrayerRequest) =
|
let reqExp (req : PrayerRequest) =
|
||||||
_class (if req.IsExpired now prefs.DaysToExpire then "pt-request-expired" else "")
|
_class (if req.IsExpired now prefs.DaysToExpire then "cell pt-request-expired" else "cell")
|
||||||
|
let vi = AppViewInfo.withScopedStyles [ "#requestList { grid-template-columns: repeat(5, auto); }" ] viewInfo
|
||||||
/// Iterate the sequence once, before we render, so we can get the count of it at the top of the table
|
/// Iterate the sequence once, before we render, so we can get the count of it at the top of the table
|
||||||
let requests =
|
let requests =
|
||||||
model.Requests
|
model.Requests
|
||||||
|
@ -175,33 +178,34 @@ let maintain (model : MaintainRequests) (ctx : HttpContext) viewInfo =
|
||||||
.Value
|
.Value
|
||||||
]
|
]
|
||||||
|> String.concat ""
|
|> String.concat ""
|
||||||
tr [] [
|
div [ _class "row" ] [
|
||||||
td [] [
|
div [ _class "cell actions" ] [
|
||||||
a [ _href $"/prayer-request/{reqId}/edit"; _title l["Edit This Prayer Request"].Value ] [
|
a [ _href $"/prayer-request/{reqId}/edit"; _title l["Edit This Prayer Request"].Value ] [
|
||||||
icon "edit"
|
iconSized 18 "edit"
|
||||||
]
|
]
|
||||||
if req.IsExpired now prefs.DaysToExpire then
|
if req.IsExpired now prefs.DaysToExpire then
|
||||||
a [ _href $"/prayer-request/{reqId}/restore"
|
a [ _href $"/prayer-request/{reqId}/restore"
|
||||||
_title l["Restore This Inactive Request"].Value ] [
|
_title l["Restore This Inactive Request"].Value ] [
|
||||||
icon "visibility"
|
iconSized 18 "visibility"
|
||||||
]
|
]
|
||||||
else
|
else
|
||||||
a [ _href $"/prayer-request/{reqId}/expire"
|
a [ _href $"/prayer-request/{reqId}/expire"
|
||||||
_title l["Expire This Request Immediately"].Value ] [
|
_title l["Expire This Request Immediately"].Value ] [
|
||||||
icon "visibility_off"
|
iconSized 18 "visibility_off"
|
||||||
]
|
]
|
||||||
a [ _href delAction
|
a [ _href delAction
|
||||||
_title l["Delete This Request"].Value
|
_title l["Delete This Request"].Value
|
||||||
_onclick $"return PT.confirmDelete('{delAction}','{delPrompt}')" ] [
|
_hxPost delAction
|
||||||
icon "delete_forever"
|
_hxConfirm delPrompt ] [
|
||||||
|
iconSized 18 "delete_forever"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
td [ updReq req ] [
|
div [ updReq req ] [
|
||||||
str (req.UpdatedDate.ToString(s["MMMM d, yyyy"].Value, Globalization.CultureInfo.CurrentUICulture))
|
str (req.UpdatedDate.ToString(s["MMMM d, yyyy"].Value, Globalization.CultureInfo.CurrentUICulture))
|
||||||
]
|
]
|
||||||
td [] [ locStr types[req.RequestType] ]
|
div [ _class "cell" ] [ locStr types[req.RequestType] ]
|
||||||
td [ reqExp req ] [ str (match req.Requestor with Some r -> r | None -> " ") ]
|
div [ reqExp req ] [ str (match req.Requestor with Some r -> r | None -> " ") ]
|
||||||
td [] [
|
div [ _class "cell" ] [
|
||||||
match reqText.Length with
|
match reqText.Length with
|
||||||
| len when len < 60 -> rawText reqText
|
| len when len < 60 -> rawText reqText
|
||||||
| _ -> rawText $"{reqText[0..59]}…"
|
| _ -> rawText $"{reqText[0..59]}…"
|
||||||
|
@ -235,9 +239,18 @@ let maintain (model : MaintainRequests) (ctx : HttpContext) viewInfo =
|
||||||
match requests.Length with
|
match requests.Length with
|
||||||
| 0 -> ()
|
| 0 -> ()
|
||||||
| _ ->
|
| _ ->
|
||||||
table [ _class "pt-table pt-action-table" ] [
|
form [ _method "post" ] [
|
||||||
tableHeadings s [ "Actions"; "Updated Date"; "Type"; "Requestor"; "Request"]
|
csrfToken ctx
|
||||||
tbody [] requests
|
section [ _id "requestList"; _class "pt-table"; _ariaLabel "Prayer request list" ] [
|
||||||
|
div [ _class "row head" ] [
|
||||||
|
header [ _class "cell" ] [ locStr s["Actions"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Updated Date"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Type"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Requestor"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Request"] ]
|
||||||
|
]
|
||||||
|
yield! requests
|
||||||
|
]
|
||||||
]
|
]
|
||||||
div [ _class "pt-center-text" ] [
|
div [ _class "pt-center-text" ] [
|
||||||
br []
|
br []
|
||||||
|
@ -272,10 +285,9 @@ let maintain (model : MaintainRequests) (ctx : HttpContext) viewInfo =
|
||||||
]
|
]
|
||||||
| false -> ()
|
| false -> ()
|
||||||
]
|
]
|
||||||
form [ _id "DeleteForm"; _action ""; _method "post" ] [ csrfToken ctx ]
|
|
||||||
]
|
]
|
||||||
|> Layout.Content.wide
|
|> Layout.Content.wide
|
||||||
|> Layout.standard viewInfo (match model.SearchTerm with Some _ -> "Search Results" | None -> "Maintain Requests")
|
|> Layout.standard vi (match model.SearchTerm with Some _ -> "Search Results" | None -> "Maintain Requests")
|
||||||
|
|
||||||
|
|
||||||
/// View for the printable prayer request list
|
/// View for the printable prayer request list
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
module PrayerTracker.Views.SmallGroup
|
module PrayerTracker.Views.SmallGroup
|
||||||
|
|
||||||
open Giraffe.ViewEngine
|
open Giraffe.ViewEngine
|
||||||
|
open Giraffe.ViewEngine.Accessibility
|
||||||
|
open Giraffe.ViewEngine.Htmx
|
||||||
open Microsoft.Extensions.Localization
|
open Microsoft.Extensions.Localization
|
||||||
open PrayerTracker
|
open PrayerTracker
|
||||||
open PrayerTracker.Entities
|
open PrayerTracker.Entities
|
||||||
|
@ -179,33 +181,40 @@ let logOn (groups : SmallGroup list) grpId ctx viewInfo =
|
||||||
|
|
||||||
/// View for the small group maintenance page
|
/// View for the small group maintenance page
|
||||||
let maintain (groups : SmallGroup list) ctx viewInfo =
|
let maintain (groups : SmallGroup list) ctx viewInfo =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let grpTbl =
|
let vi = AppViewInfo.withScopedStyles [ "#groupList { grid-template-columns: repeat(4, auto); }" ] viewInfo
|
||||||
|
let groupTable =
|
||||||
match groups with
|
match groups with
|
||||||
| [] -> space
|
| [] -> space
|
||||||
| _ ->
|
| _ ->
|
||||||
table [ _class "pt-table pt-action-table" ] [
|
section [ _id "groupList"; _class "pt-table"; _ariaLabel "Small group list" ] [
|
||||||
tableHeadings s [ "Actions"; "Name"; "Church"; "Time Zone"]
|
div [ _class "row head" ] [
|
||||||
groups
|
header [ _class "cell" ] [ locStr s["Actions"] ]
|
||||||
|> List.map (fun g ->
|
header [ _class "cell" ] [ locStr s["Name"] ]
|
||||||
let grpId = shortGuid g.Id.Value
|
header [ _class "cell" ] [ locStr s["Church"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Time Zone"] ]
|
||||||
|
]
|
||||||
|
for group in groups do
|
||||||
|
let grpId = shortGuid group.Id.Value
|
||||||
let delAction = $"/small-group/{grpId}/delete"
|
let delAction = $"/small-group/{grpId}/delete"
|
||||||
let delPrompt = s["Are you sure you want to delete this {0}? This action cannot be undone.",
|
let delPrompt = s["Are you sure you want to delete this {0}? This action cannot be undone.",
|
||||||
$"""{s["Small Group"].Value.ToLower ()} ({g.Name})""" ].Value
|
$"""{s["Small Group"].Value.ToLower ()} ({group.Name})""" ].Value
|
||||||
tr [] [
|
div [ _class "row" ] [
|
||||||
td [] [
|
div [ _class "cell actions" ] [
|
||||||
a [ _href $"/small-group/{grpId}/edit"; _title s["Edit This Group"].Value ] [ icon "edit" ]
|
a [ _href $"/small-group/{grpId}/edit"; _title s["Edit This Group"].Value ] [
|
||||||
a [ _href delAction
|
iconSized 18 "edit"
|
||||||
_title s["Delete This Group"].Value
|
]
|
||||||
_onclick $"return PT.confirmDelete('{delAction}','{delPrompt}')" ] [
|
a [ _href delAction
|
||||||
icon "delete_forever"
|
_title s["Delete This Group"].Value
|
||||||
|
_hxDelete delAction
|
||||||
|
_hxConfirm delPrompt ] [
|
||||||
|
iconSized 18 "delete_forever"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
td [] [ str g.Name ]
|
div [ _class "cell" ] [ str group.Name ]
|
||||||
td [] [ str g.Church.Name ]
|
div [ _class "cell" ] [ str group.Church.Name ]
|
||||||
td [] [ locStr (TimeZones.name g.Preferences.TimeZoneId s) ]
|
div [ _class "cell" ] [ locStr (TimeZones.name group.Preferences.TimeZoneId s) ]
|
||||||
])
|
]
|
||||||
|> tbody []
|
|
||||||
]
|
]
|
||||||
[ div [ _class "pt-center-text" ] [
|
[ div [ _class "pt-center-text" ] [
|
||||||
br []
|
br []
|
||||||
|
@ -216,45 +225,54 @@ let maintain (groups : SmallGroup list) ctx viewInfo =
|
||||||
br []
|
br []
|
||||||
]
|
]
|
||||||
tableSummary groups.Length s
|
tableSummary groups.Length s
|
||||||
grpTbl
|
form [ _method "post" ] [
|
||||||
form [ _id "DeleteForm"; _action ""; _method "post" ] [ csrfToken ctx ]
|
csrfToken ctx
|
||||||
|
groupTable
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard viewInfo "Maintain Groups"
|
|> Layout.standard vi "Maintain Groups"
|
||||||
|
|
||||||
|
|
||||||
/// View for the member maintenance page
|
/// View for the member maintenance page
|
||||||
let members (members : Member list) (emailTypes : Map<string, LocalizedString>) ctx viewInfo =
|
let members (members : Member list) (emailTypes : Map<string, LocalizedString>) ctx viewInfo =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let mbrTbl =
|
let vi = AppViewInfo.withScopedStyles [ "#memberList { grid-template-columns: repeat(4, auto); }" ] viewInfo
|
||||||
|
let memberTable =
|
||||||
match members with
|
match members with
|
||||||
| [] -> space
|
| [] -> space
|
||||||
| _ ->
|
| _ ->
|
||||||
table [ _class "pt-table pt-action-table" ] [
|
section [ _id "memberList"; _class "pt-table"; _ariaLabel "Small group member list" ] [
|
||||||
tableHeadings s [ "Actions"; "Name"; "E-mail Address"; "Format"]
|
div [ _class "row head" ] [
|
||||||
members
|
header [ _class "cell"] [ locStr s["Actions"] ]
|
||||||
|> List.map (fun mbr ->
|
header [ _class "cell"] [ locStr s["Name"] ]
|
||||||
|
header [ _class "cell"] [ locStr s["E-mail Address"] ]
|
||||||
|
header [ _class "cell"] [ locStr s["Format"] ]
|
||||||
|
]
|
||||||
|
for mbr in members do
|
||||||
let mbrId = shortGuid mbr.Id.Value
|
let mbrId = shortGuid mbr.Id.Value
|
||||||
let delAction = $"/small-group/member/{mbrId}/delete"
|
let delAction = $"/small-group/member/{mbrId}/delete"
|
||||||
let delPrompt =
|
let delPrompt =
|
||||||
s["Are you sure you want to delete this {0}? This action cannot be undone.", s["group member"]]
|
s["Are you sure you want to delete this {0}? This action cannot be undone.", s["group member"]]
|
||||||
.Value.Replace("?", $" ({mbr.Name})?")
|
.Value.Replace("?", $" ({mbr.Name})?")
|
||||||
tr [] [
|
div [ _class "row" ] [
|
||||||
td [] [
|
div [ _class "cell actions" ] [
|
||||||
a [ _href $"/small-group/member/{mbrId}/edit"; _title s["Edit This Group Member"].Value ] [
|
a [ _href $"/small-group/member/{mbrId}/edit"; _title s["Edit This Group Member"].Value ] [
|
||||||
icon "edit"
|
iconSized 18 "edit"
|
||||||
]
|
]
|
||||||
a [ _href delAction
|
a [ _href delAction
|
||||||
_title s["Delete This Group Member"].Value
|
_title s["Delete This Group Member"].Value
|
||||||
_onclick $"return PT.confirmDelete('{delAction}','{delPrompt}')" ] [
|
_hxPost delAction
|
||||||
icon "delete_forever"
|
_hxConfirm delPrompt ] [
|
||||||
|
iconSized 18 "delete_forever"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
td [] [ str mbr.Name ]
|
div [ _class "cell" ] [ str mbr.Name ]
|
||||||
td [] [ str mbr.Email ]
|
div [ _class "cell" ] [ str mbr.Email ]
|
||||||
td [] [ locStr emailTypes[defaultArg (mbr.Format |> Option.map EmailFormat.toCode) ""] ]
|
div [ _class "cell" ] [
|
||||||
])
|
locStr emailTypes[defaultArg (mbr.Format |> Option.map EmailFormat.toCode) ""]
|
||||||
|> tbody []
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
[ div [ _class"pt-center-text" ] [
|
[ div [ _class"pt-center-text" ] [
|
||||||
br []
|
br []
|
||||||
|
@ -265,15 +283,15 @@ let members (members : Member list) (emailTypes : Map<string, LocalizedString>)
|
||||||
br []
|
br []
|
||||||
]
|
]
|
||||||
tableSummary members.Length s
|
tableSummary members.Length s
|
||||||
mbrTbl
|
form [ _method "post" ] [
|
||||||
form [ _id "DeleteForm"; _action ""; _method "post" ] [ csrfToken ctx ]
|
csrfToken ctx
|
||||||
|
memberTable
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard viewInfo "Maintain Group Members"
|
|> Layout.standard vi "Maintain Group Members"
|
||||||
|
|
||||||
|
|
||||||
open Giraffe.ViewEngine.Accessibility
|
|
||||||
|
|
||||||
/// View for the small group overview page
|
/// View for the small group overview page
|
||||||
let overview model viewInfo =
|
let overview model viewInfo =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
module PrayerTracker.Views.User
|
module PrayerTracker.Views.User
|
||||||
|
|
||||||
open Giraffe.ViewEngine
|
open Giraffe.ViewEngine
|
||||||
|
open Giraffe.ViewEngine.Accessibility
|
||||||
|
open Giraffe.ViewEngine.Htmx
|
||||||
open PrayerTracker
|
open PrayerTracker
|
||||||
open PrayerTracker.ViewModels
|
open PrayerTracker.ViewModels
|
||||||
|
|
||||||
|
@ -8,37 +10,33 @@ open PrayerTracker.ViewModels
|
||||||
let assignGroups model groups curGroups ctx viewInfo =
|
let assignGroups model groups curGroups ctx viewInfo =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let pageTitle = sprintf "%s • %A" model.UserName s["Assign Groups"]
|
let pageTitle = sprintf "%s • %A" model.UserName s["Assign Groups"]
|
||||||
|
let vi = AppViewInfo.withScopedStyles [ "#groupList { grid-template-columns: auto; }" ] viewInfo
|
||||||
form [ _action "/user/small-groups/save"; _method "post"; _class "pt-center-columns"; Target.content ] [
|
form [ _action "/user/small-groups/save"; _method "post"; _class "pt-center-columns"; Target.content ] [
|
||||||
csrfToken ctx
|
csrfToken ctx
|
||||||
inputField "hidden" (nameof model.UserId) model.UserId []
|
inputField "hidden" (nameof model.UserId) model.UserId []
|
||||||
inputField "hidden" (nameof model.UserName) model.UserName []
|
inputField "hidden" (nameof model.UserName) model.UserName []
|
||||||
table [ _class "pt-table" ] [
|
section [ _id "groupList"; _class "pt-table"; _ariaLabel "Assigned small groups" ] [
|
||||||
thead [] [
|
div [ _class "row head" ] [
|
||||||
tr [] [
|
header [ _class "cell" ] [ locStr s["Group"] ]
|
||||||
th [] [ rawText " " ]
|
|
||||||
th [] [ locStr s["Group"] ]
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
groups
|
for groupId, name in groups do
|
||||||
|> List.map (fun (grpId, grpName) ->
|
div [ _class "row" ] [
|
||||||
let inputId = $"id-{grpId}"
|
div [ _class "cell" ] [
|
||||||
tr [] [
|
|
||||||
td [] [
|
|
||||||
input [ _type "checkbox"
|
input [ _type "checkbox"
|
||||||
_name (nameof model.SmallGroups)
|
_name (nameof model.SmallGroups)
|
||||||
_id inputId
|
_id groupId
|
||||||
_value grpId
|
_value groupId
|
||||||
if List.contains grpId curGroups then _checked ]
|
if List.contains groupId curGroups then _checked ]
|
||||||
|
space
|
||||||
|
label [ _for groupId ] [ str name ]
|
||||||
]
|
]
|
||||||
td [] [ label [ _for inputId ] [ str grpName ] ]
|
]
|
||||||
])
|
|
||||||
|> tbody []
|
|
||||||
]
|
]
|
||||||
div [ _fieldRow ] [ submit [] "save" s["Save Group Assignments"] ]
|
div [ _fieldRow ] [ submit [] "save" s["Save Group Assignments"] ]
|
||||||
]
|
]
|
||||||
|> List.singleton
|
|> List.singleton
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard viewInfo pageTitle
|
|> Layout.standard vi pageTitle
|
||||||
|
|
||||||
|
|
||||||
/// View for the password change page
|
/// View for the password change page
|
||||||
|
@ -186,40 +184,45 @@ open PrayerTracker.Entities
|
||||||
|
|
||||||
/// View for the user maintenance page
|
/// View for the user maintenance page
|
||||||
let maintain (users : User list) ctx viewInfo =
|
let maintain (users : User list) ctx viewInfo =
|
||||||
let s = I18N.localizer.Force ()
|
let s = I18N.localizer.Force ()
|
||||||
let usrTbl =
|
let vi = AppViewInfo.withScopedStyles [ "#userList { grid-template-columns: repeat(4, auto); }" ] viewInfo
|
||||||
|
let userTable =
|
||||||
match users with
|
match users with
|
||||||
| [] -> space
|
| [] -> space
|
||||||
| _ ->
|
| _ ->
|
||||||
table [ _class "pt-table pt-action-table" ] [
|
section [ _id "userList"; _class "pt-table"; _ariaLabel "User list" ] [
|
||||||
tableHeadings s [ "Actions"; "Name"; "Last Seen"; "Admin?" ]
|
div [ _class "row head" ] [
|
||||||
users
|
header [ _class "cell" ] [ locStr s["Actions"] ]
|
||||||
|> List.map (fun user ->
|
header [ _class "cell" ] [ locStr s["Name"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Last Seen"] ]
|
||||||
|
header [ _class "cell" ] [ locStr s["Admin?"] ]
|
||||||
|
]
|
||||||
|
for user in users do
|
||||||
let userId = shortGuid user.Id.Value
|
let userId = shortGuid user.Id.Value
|
||||||
let delAction = $"/user/{userId}/delete"
|
let delAction = $"/user/{userId}/delete"
|
||||||
let delPrompt = s["Are you sure you want to delete this {0}? This action cannot be undone.",
|
let delPrompt = s["Are you sure you want to delete this {0}? This action cannot be undone.",
|
||||||
$"""{s["User"].Value.ToLower ()} ({user.Name})"""].Value
|
$"""{s["User"].Value.ToLower ()} ({user.Name})"""].Value
|
||||||
tr [] [
|
div [ _class "row" ] [
|
||||||
td [] [
|
div [ _class "cell actions" ] [
|
||||||
a [ _href $"/user/{userId}/edit"; _title s["Edit This User"].Value ] [ icon "edit" ]
|
a [ _href $"/user/{userId}/edit"; _title s["Edit This User"].Value ] [ iconSized 18 "edit" ]
|
||||||
a [ _href $"/user/{userId}/small-groups"; _title s["Assign Groups to This User"].Value ] [
|
a [ _href $"/user/{userId}/small-groups"; _title s["Assign Groups to This User"].Value ] [
|
||||||
icon "group"
|
iconSized 18 "group"
|
||||||
]
|
]
|
||||||
a [ _href delAction
|
a [ _href delAction
|
||||||
_title s["Delete This User"].Value
|
_title s["Delete This User"].Value
|
||||||
_onclick $"return PT.confirmDelete('{delAction}','{delPrompt}')" ] [
|
_hxPost delAction
|
||||||
icon "delete_forever"
|
_hxConfirm delPrompt ] [
|
||||||
|
iconSized 18 "delete_forever"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
td [] [ str user.Name ]
|
div [ _class "cell" ] [ str user.Name ]
|
||||||
td [] [
|
div [ _class "cell" ] [
|
||||||
str (match user.LastSeen with Some dt -> dt.ToString s["MMMM d, yyyy"] | None -> "--")
|
str (match user.LastSeen with Some dt -> dt.ToString s["MMMM d, yyyy"] | None -> "--")
|
||||||
]
|
]
|
||||||
td [ _class "pt-center-text" ] [
|
div [ _class "cell pt-center-text" ] [
|
||||||
if user.IsAdmin then strong [] [ locStr s["Yes"] ] else locStr s["No"]
|
if user.IsAdmin then strong [] [ locStr s["Yes"] ] else locStr s["No"]
|
||||||
]
|
]
|
||||||
])
|
]
|
||||||
|> tbody []
|
|
||||||
]
|
]
|
||||||
[ div [ _class "pt-center-text" ] [
|
[ div [ _class "pt-center-text" ] [
|
||||||
br []
|
br []
|
||||||
|
@ -230,8 +233,10 @@ let maintain (users : User list) ctx viewInfo =
|
||||||
br []
|
br []
|
||||||
]
|
]
|
||||||
tableSummary users.Length s
|
tableSummary users.Length s
|
||||||
usrTbl
|
form [ _method "post" ] [
|
||||||
form [ _id "DeleteForm"; _action ""; _method "post" ] [ csrfToken ctx ]
|
csrfToken ctx
|
||||||
|
userTable
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|> Layout.Content.standard
|
|> Layout.Content.standard
|
||||||
|> Layout.standard viewInfo "Maintain Users"
|
|> Layout.standard vi "Maintain Users"
|
||||||
|
|
|
@ -263,54 +263,48 @@ footer a:hover {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pt-data-list {
|
.pt-table {
|
||||||
display: grid;
|
display: grid;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
grid-row-gap: .5rem;
|
|
||||||
grid-column-gap: 1rem;
|
|
||||||
}
|
}
|
||||||
.pt-data-list .row {
|
.pt-table .row.head,
|
||||||
|
.pt-table .row {
|
||||||
display: contents;
|
display: contents;
|
||||||
}
|
}
|
||||||
.pt-data-list .row:hover > * {
|
.pt-table .row:hover > * {
|
||||||
background-color: purple;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pt-table {
|
|
||||||
margin: auto;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
.pt-table thead {
|
|
||||||
background-image: linear-gradient(to bottom, var(--dark), var(--lighter-dark));
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.pt-table tbody tr:hover {
|
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
.pt-table tr th,
|
.pt-table .row.head .cell {
|
||||||
.pt-table tr td {
|
background-image: linear-gradient(to bottom, var(--dark), var(--lighter-dark));
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
font-size: .85rem;
|
||||||
|
}
|
||||||
|
.pt-table .row.head .cell:first-of-type {
|
||||||
|
border-top-left-radius: .5rem;
|
||||||
|
}
|
||||||
|
.pt-table .row.head .cell:last-of-type {
|
||||||
|
border-top-right-radius: .5rem;
|
||||||
|
}
|
||||||
|
.pt-table .cell {
|
||||||
padding: .25rem .5rem;
|
padding: .25rem .5rem;
|
||||||
|
border-bottom: dotted 1px var(--lighter-dark);
|
||||||
}
|
}
|
||||||
.pt-table tbody tr td {
|
.pt-table .cell.actions {
|
||||||
border-bottom: solid 1px var(--lighter-dark);
|
border-bottom-color: var(--background);
|
||||||
}
|
}
|
||||||
.pt-action-table tbody tr td:first-child {
|
.pt-table .cell.actions a {
|
||||||
white-space: nowrap;
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
.pt-action-table tbody tr td:first-child a {
|
|
||||||
background-color: gray;
|
background-color: gray;
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: .5rem;
|
border-radius: .5rem;
|
||||||
padding: .125rem .5rem .5rem .5rem;
|
padding: 0 .5rem .25rem;
|
||||||
margin: 0 .125rem;
|
margin: 0 .125rem;
|
||||||
}
|
}
|
||||||
.pt-action-table tbody tr:hover td:first-child a {
|
.pt-table .row:hover .cell.actions a {
|
||||||
background-color: var(--dark);
|
background-color: var(--dark);
|
||||||
}
|
}
|
||||||
.pt-action-table tbody tr td:first-child a:hover {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
/* TODO: Figure out nice CSS transitions for these; these don't work */
|
/* TODO: Figure out nice CSS transitions for these; these don't work */
|
||||||
.pt-fadeable {
|
.pt-fadeable {
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user