diff --git a/main.go b/main.go index d74d10c..655206e 100644 --- a/main.go +++ b/main.go @@ -76,6 +76,7 @@ func setupEcho() *echo.Echo { e.GET("/sideboxes", ui.AmWrap(ManageSideboxes)) e.POST("/sideboxes", ui.AmWrap(AddSidebox)) e.GET("/sysadmin", ui.AmWrap(SysAdminMenu)) + e.GET("/sysadmin/globals", ui.AmWrap(GlobalPropertiesForm)) e.GET("/create_comm", ui.AmWrap(CreateCommunityForm)) e.POST("/create_comm", ui.AmWrap(CreateCommunity)) e.GET("/manage_comm", ui.AmWrap(ManageCommunities)) diff --git a/sysadmin.go b/sysadmin.go index 74f9ba4..4d69e7e 100644 --- a/sysadmin.go +++ b/sysadmin.go @@ -1,6 +1,6 @@ /* * Amsterdam Web Communities System - * Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved + * Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -23,8 +23,7 @@ import ( * Data as a parameter for the command string. */ func SysAdminMenu(ctxt ui.AmContext) (string, any) { - u := ctxt.CurrentUser() - if !database.AmTestPermission("Global.SysAdminAccess", u.BaseLevel) { + if !database.AmTestPermission("Global.SysAdminAccess", ctxt.CurrentUser().BaseLevel) { return "error", ENOACCESS } menu := ui.AmMenu("sysadmin") @@ -33,3 +32,32 @@ func SysAdminMenu(ctxt ui.AmContext) (string, any) { ctxt.SetFrameTitle(menu.Title) return "framed", "menu.jet" } + +/* GlobalPropertiesForm displays the global properties editing form. + * Parameters: + * ctxt - The AmContext for the request. + * Returns: + * Command string dictating what to be rendered. + * Data as a parameter for the command string. + */ +func GlobalPropertiesForm(ctxt ui.AmContext) (string, any) { + if !database.AmTestPermission("Global.SysAdminAccess", ctxt.CurrentUser().BaseLevel) { + return "error", ENOACCESS + } + + dlg, err := ui.AmLoadDialog("globalprops") + if err != nil { + return "error", err + } + dlg.Field("search_items").SetInt(int(ctxt.Globals().MaxSearchPage)) + dlg.Field("fp_posts").SetInt(int(ctxt.Globals().FrontPagePosts)) + dlg.Field("audit_recs").SetInt(int(ctxt.Globals().NumAuditPage)) + dlg.Field("create_lvl").SetLevel(uint16(ctxt.Globals().CommunityCreateLevel)) + dlg.Field("comm_mbrs").SetInt(int(ctxt.Globals().MaxCommunityMemberPage)) + dlg.Field("no_cats").SetChecked(ctxt.GlobalFlags().Get(database.GlobalFlagNoCategories)) + dlg.Field("posts_page").SetInt(int(ctxt.Globals().PostsPerPage)) + dlg.Field("old_posts").SetInt(int(ctxt.Globals().OldPostsAtTop)) + dlg.Field("conf_mbrs").SetInt(int(ctxt.Globals().MaxConferenceMemberPage)) + dlg.Field("pic_in_post").SetChecked(ctxt.GlobalFlags().Get(database.GlobalFlagPicturesInPosts)) + return dlg.Render(ctxt) +} diff --git a/ui/dialog.go b/ui/dialog.go index ce05b1e..74bbe25 100644 --- a/ui/dialog.go +++ b/ui/dialog.go @@ -13,6 +13,7 @@ package ui import ( "embed" "fmt" + "math" "net/mail" "strconv" "strings" @@ -66,6 +67,11 @@ type VRange struct { High int } +// IsEmpty tells us if a value range is empty. +func (vr *VRange) IsEmpty() bool { + return vr.Low == -1 && vr.High == -1 +} + //go:embed dialogs/* var dialogs embed.FS @@ -92,6 +98,16 @@ func AmLoadDialog(name string) (*Dialog, error) { if fld.Type == "date" && fld.Param == "" { d.Fields[i].Param = "year:-100" } + if fld.Type == "integer" && fld.Size == 0 { + vr := fld.ValueRange() + if !vr.IsEmpty() { + // compute the number of digits in each end of the range and take the maximum as the size + dlow := int(math.Floor(math.Log10(float64(vr.Low)))) + 1 + dhigh := int(math.Floor(math.Log10(float64(vr.High)))) + 1 + d.Fields[i].Size = max(dlow, dhigh) + d.Fields[i].MaxLength = d.Fields[i].Size + } + } if fld.Type == "dropdown" && len(fld.Choices) == 0 { return nil, fmt.Errorf("dropdown field %s in dialog %s has no choices", fld.Name, name) } diff --git a/ui/dialogs/globalprops.yaml b/ui/dialogs/globalprops.yaml new file mode 100644 index 0000000..dff153a --- /dev/null +++ b/ui/dialogs/globalprops.yaml @@ -0,0 +1,71 @@ +# +# Amsterdam Web Communities System +# Copyright (c) 2025-2026 Erbosoft Metaverse Design Solutions, All Rights Reserved +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +name: "global.properties" +formName: "globpropform" +menuSelector: "nochange" +title: "Edit Global Properties" +action: "/sysadmin/globals" +fields: + - type: "header" + name: "header1" + caption: "System Properties" + - type: "integer" + name: "search_items" + caption: "Number of search items to display per page" + param: "5-100" + - type: "integer" + name: "fp_posts" + caption: "Number of published posts to display on front page" + param: "1-50" + - type: "integer" + name: "audit_recs" + caption: "Number of audit records to display per page" + param: "10-500" + - type: "rolelist" + name: "create_lvl" + caption: "Security level required to create a new community" + required: true + param: "Global.CreateCommunity" + - type: "header" + name: "header2" + caption: "Community Properties" + - type: "integer" + name: "comm_mbrs" + caption: "Number of community members to display per page" + param: "10-100" + - type: "checkbox" + name: "no_cats" + caption: "Disable community categorization system" + - type: "header" + name: "header2" + caption: "Conferencing Properties" + - type: "integer" + name: "posts_page" + caption: "Maximum number of posts to display per page" + param: "5-100" + - type: "integer" + name: "old_posts" + caption: "Number of 'old' posts to display at top of page" + param: "1-5" + - type: "integer" + name: "conf_mbrs" + caption: "Number of conference members to display per page" + param: "10-100" + - type: "checkbox" + name: "pic_in_post" + caption: "Display user pictures next to posts in conference" + subcaption: "(by default; user can override)" + - type: "button" + name: "update" + caption: "Update" + param: "blue" + - type: "button" + name: "cancel" + caption: "Cancel" + param: "red" diff --git a/ui/menudefs.yaml b/ui/menudefs.yaml index 18b9a6d..e01135c 100644 --- a/ui/menudefs.yaml +++ b/ui/menudefs.yaml @@ -34,7 +34,7 @@ menudefs: Use with care and review all changes before applying them to the system. items: - text: "Edit Global Properties" - link: "/TODO/sysadmin/global" + link: "/sysadmin/globals" permission: "Global.SysAdminAccess" - text: "View/Edit IP Address Bans" link: "/TODO/sysadmin/ip_bans"