diff --git a/communityadmin.go b/communityadmin.go index df3a43f..bc6225d 100644 --- a/communityadmin.go +++ b/communityadmin.go @@ -422,6 +422,63 @@ func CommunityAudit(ctxt ui.AmContext) (string, any) { return "framed", "audit.jet" } +/* CommunityCategory handles setting the community category. + * Parameters: + * ctxt - The AmContext for the request. + * Returns: + * Command string dictating what to be rendered. + * Data as a parameter for the command string. + * Standard Go error status. + */ +func CommunityCategory(ctxt ui.AmContext) (string, any) { + if ctxt.GlobalFlags().Get(database.GlobalFlagNoCategories) { + return "error", "This instance of Amsterdam does not use the categorization system." + } + comm := ctxt.CurrentCommunity() + if !comm.TestPermission("Community.Write", ctxt.EffectiveLevel()) { + return "error", ENOACCESS + } + + if setId := ctxt.QueryParamInt("set", -1); setId >= 0 { + err := comm.SetCategory(ctxt.Ctx(), int32(setId), ctxt.CurrentUser(), ctxt.RemoteIP()) + if err != nil { + return "error", err + } + return "redirect", fmt.Sprintf("/comm/%s/admin", comm.Alias) + } + + currentCat, err := database.AmGetCategory(ctxt.Ctx(), comm.CategoryId) + if err != nil { + return "error", err + } + + displayId := ctxt.QueryParamInt("d", int(comm.CategoryId)) + var newCat []*database.Category + if displayId >= 0 { + newCat, err = database.AmGetCategoryHierarchy(ctxt.Ctx(), int32(displayId)) + if err != nil { + return "error", err + } + } else { + newCat = make([]*database.Category, 0) + } + + subCats, err := database.AmGetSubCategories(ctxt.Ctx(), int32(displayId)) + if err != nil { + return "error", err + } + + ctxt.VarMap().Set("commName", comm.Name) + ctxt.VarMap().Set("oldCat", currentCat) + ctxt.VarMap().Set("newCat", newCat) + ctxt.VarMap().Set("newCatId", displayId) + ctxt.VarMap().Set("subCats", subCats) + ctxt.VarMap().Set("backLink", fmt.Sprintf("/comm/%s/admin", comm.Alias)) + ctxt.VarMap().Set("selfLink", fmt.Sprintf("/comm/%s/admin/category", comm.Alias)) + ctxt.SetFrameTitle("Set Community Category") + return "framed", "comm_category.jet" +} + /* CreateCommunityForm renders the form for creating a new community. * Parameters: * ctxt - The AmContext for the request. diff --git a/database/category.go b/database/category.go index d0e28e4..6073119 100644 --- a/database/category.go +++ b/database/category.go @@ -143,11 +143,8 @@ func AmGetCategoryHierarchy(ctx context.Context, catid int32) ([]*Category, erro p = c.Parent } // reverse the array for return - rc := make([]*Category, 0, len(ia)) - for i := range ia { - rc = append(rc, ia[len(ia)-(i+1)]) - } - return rc, nil + slices.Reverse(ia) + return ia, nil } /* AmGetSubCategories returns a list of all subcategories of the given category ID. diff --git a/database/community.go b/database/community.go index 9a40f6b..7b58dee 100644 --- a/database/community.go +++ b/database/community.go @@ -461,6 +461,20 @@ func (c *Community) SaveFlags(ctx context.Context, f *util.OptionSet) error { return err } +// SetCategory sets the community's category ID. +func (c *Community) SetCategory(ctx context.Context, catId int32, u *User, ipaddr string) error { + c.Mutex.Lock() + defer c.Mutex.Unlock() + _, err := amdb.ExecContext(ctx, "UPDATE communities SET catid = ? WHERE commid = ?", catId, c.Id) + if err == nil { + if catId != c.CategoryId { + AmStoreAudit(AmNewCommAudit(AuditCommunityCategory, u.Uid, c.Id, ipaddr, fmt.Sprintf("catid=%d", catId))) + } + c.CategoryId = catId + } + return err +} + // SetProfileData sets all the "settable" profile data func (c *Community) SetProfileData(ctx context.Context, name string, alias string, synopsis *string, rules *string, language *string, joinkey *string, membersonly bool, hideDirectory bool, hideSearch bool, read_lvl uint16, write_lvl uint16, diff --git a/docs/MISSINGFUNCS.md b/docs/MISSINGFUNCS.md index 2008fdd..63e2c5d 100644 --- a/docs/MISSINGFUNCS.md +++ b/docs/MISSINGFUNCS.md @@ -24,7 +24,7 @@ _(italicized items can be deferred)_ - ~~Create New~~ - ~~Conferences List honor "hide in list" flag~~ - Community Admin Menu: - - Set Community Category + - ~~Set Community Category~~ - Membership Control - E-Mail to All Members - ~~Display Audit Records~~ diff --git a/main.go b/main.go index bfc079f..e922b2f 100644 --- a/main.go +++ b/main.go @@ -116,6 +116,7 @@ func setupEcho() *echo.Echo { commGroup.GET("/admin/logo", ui.AmWrap(CommunityLogoForm)) commGroup.POST("/admin/logo", ui.AmWrap(EditCommunityLogo)) commGroup.Match(GetAndPost, "/admin/audit", ui.AmWrap(CommunityAudit)) + commGroup.GET("/admin/category", ui.AmWrap(CommunityCategory)) // conference group commGroup.GET("/create_conf", ui.AmWrap(CreateConferenceForm)) diff --git a/ui/menudefs.yaml b/ui/menudefs.yaml index 3cd71e5..8b8311e 100644 --- a/ui/menudefs.yaml +++ b/ui/menudefs.yaml @@ -53,7 +53,7 @@ menudefs: link: "/TODO/sysadmin/import" permission: "Global.SysAdminAccess" - id: "communityadmin" - title: "Community Administration" + title: "Community Administration:" subtitle: "[CNAME]" permSet: "community" warning: > @@ -64,7 +64,7 @@ menudefs: link: "/comm/[CID]/admin/profile" permission: "Community.Write" - text: "Set Community Category" - link: "/TODO/comm/[CID]/admin/category" + link: "/comm/[CID]/admin/category" permission: "Community.Write" ifdef: "USECAT" - text: "Set Community Services" diff --git a/ui/views/comm_category.jet b/ui/views/comm_category.jet new file mode 100644 index 0000000..d1a15c4 --- /dev/null +++ b/ui/views/comm_category.jet @@ -0,0 +1,86 @@ +{* + * 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/. + *} +
| + 🟣 + {{ c.Name }} + | ++ {{ if c.CatId != oldCat.CatId }} + *️⃣ + {{ else }} + + {{ end }} + | +
Changing the Community's Category:
+Click on a subcategory name to make that category the currently-displayed one.
+Click on a *️⃣ icon to set that category as the community's new category and return to the Community Administration menu.
+