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