implemented the community admin menu and necessary tweaks to the menu system
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Amsterdam Web Communities System
|
||||||
|
* Copyright (c) 2025 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/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package main contains the high-level Amsterdam logic.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.erbosoft.com/amy/amsterdam/database"
|
||||||
|
"git.erbosoft.com/amy/amsterdam/ui"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* CommunityAdminMenu renders the community administration menu.
|
||||||
|
* 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 CommunityAdminMenu(ctxt ui.AmContext) (string, any, error) {
|
||||||
|
err := ctxt.SetCommunityContext(ctxt.URLParam("cid"))
|
||||||
|
if err != nil {
|
||||||
|
ctxt.SetRC(http.StatusNotFound)
|
||||||
|
return ui.ErrorPage(ctxt, err)
|
||||||
|
}
|
||||||
|
comm := ctxt.CurrentCommunity()
|
||||||
|
if !comm.TestPermission("Community.ShowAdmin", ctxt.EffectiveLevel()) {
|
||||||
|
ctxt.SetRC(http.StatusForbidden)
|
||||||
|
return ui.ErrorPage(ctxt, errors.New("you are not permitted to access this page"))
|
||||||
|
}
|
||||||
|
menu := ui.AmMenu("communityadmin")
|
||||||
|
defs := make(map[string]bool)
|
||||||
|
if !ctxt.GlobalFlags().Get(database.GlobalFlagNoCategories) {
|
||||||
|
defs["USECAT"] = true
|
||||||
|
}
|
||||||
|
ctxt.SetLeftMenu("community")
|
||||||
|
ctxt.VarMap().Set("menu", menu.FilterCommunity(comm))
|
||||||
|
ctxt.VarMap().Set("defs", defs)
|
||||||
|
ctxt.VarMap().Set("amsterdam_pageTitle", menu.Title+" - "+comm.Name)
|
||||||
|
return "framed_template", "menu.jet", nil
|
||||||
|
}
|
||||||
@@ -184,3 +184,5 @@ permissions:
|
|||||||
role: "Community.AnyAdmin"
|
role: "Community.AnyAdmin"
|
||||||
- name: "Community.MassMail"
|
- name: "Community.MassMail"
|
||||||
role: "Community.AnyAdmin"
|
role: "Community.AnyAdmin"
|
||||||
|
- name: "Community.Destroy"
|
||||||
|
role: "Community.Host"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ domains:
|
|||||||
requirePermission: "Community.Read"
|
requirePermission: "Community.Read"
|
||||||
requireRole: "Community.AnyAdmin"
|
requireRole: "Community.AnyAdmin"
|
||||||
linkSequence: 5000
|
linkSequence: 5000
|
||||||
link: "/TODO/comm/[CID]/admin"
|
link: "/comm/[CID]/admin"
|
||||||
title: "Administration"
|
title: "Administration"
|
||||||
- id: "SysAdmin"
|
- id: "SysAdmin"
|
||||||
index: 2
|
index: 2
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ func setupEcho() *echo.Echo {
|
|||||||
e.POST("/quick_email", ui.AmWrap(QuickEMail))
|
e.POST("/quick_email", ui.AmWrap(QuickEMail))
|
||||||
e.GET("/sysadmin", ui.AmWrap(SysAdminMenu))
|
e.GET("/sysadmin", ui.AmWrap(SysAdminMenu))
|
||||||
e.GET("/comm/:cid/profile", ui.AmWrap(ShowCommunity))
|
e.GET("/comm/:cid/profile", ui.AmWrap(ShowCommunity))
|
||||||
|
e.GET("/comm/:cid/admin", ui.AmWrap(CommunityAdminMenu))
|
||||||
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func SysAdminMenu(ctxt ui.AmContext) (string, any, error) {
|
|||||||
}
|
}
|
||||||
menu := ui.AmMenu("sysadmin")
|
menu := ui.AmMenu("sysadmin")
|
||||||
ctxt.VarMap().Set("menu", menu)
|
ctxt.VarMap().Set("menu", menu)
|
||||||
|
ctxt.VarMap().Set("defs", make(map[string]bool))
|
||||||
ctxt.VarMap().Set("amsterdam_pageTitle", menu.Title)
|
ctxt.VarMap().Set("amsterdam_pageTitle", menu.Title)
|
||||||
return "framed_template", "menu.jet", nil
|
return "framed_template", "menu.jet", nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,3 +52,35 @@ menudefs:
|
|||||||
- text: "Import User Accounts"
|
- text: "Import User Accounts"
|
||||||
link: "/TODO/sysadmin/import"
|
link: "/TODO/sysadmin/import"
|
||||||
permission: "Global.SysAdminAccess"
|
permission: "Global.SysAdminAccess"
|
||||||
|
- id: "communityadmin"
|
||||||
|
title: "Community Administration"
|
||||||
|
subtitle: "[CNAME]"
|
||||||
|
permSet: "community"
|
||||||
|
warning: >
|
||||||
|
<strong>Note:</strong> These tools provide access to sensitive administrative features for the
|
||||||
|
community. Use with care and review all changes before applying them to the community.
|
||||||
|
items:
|
||||||
|
- text: "Community Profile"
|
||||||
|
link: "/TODO/comm/[CID]/admin/profile"
|
||||||
|
permission: "Community.ShowAdmin"
|
||||||
|
- text: "Set Community Category"
|
||||||
|
link: "/TODO/comm/[CID]/admin/category"
|
||||||
|
permission: "Community.ShowAdmin"
|
||||||
|
ifdef: "USECAT"
|
||||||
|
- text: "Set Community Services"
|
||||||
|
link: "/TODO/comm/[CID]/admin/services"
|
||||||
|
permission: "Community.ShowAdmin"
|
||||||
|
disabled: true
|
||||||
|
- text: "Membership Control"
|
||||||
|
link: "/TODO/comm/[CID]/admin/members"
|
||||||
|
permission: "Community.ShowAdmin"
|
||||||
|
- text: "E-Mail to All Members"
|
||||||
|
link: "/TODO/comm/[CID]/admin/massmail"
|
||||||
|
permission: "Community.MassMail"
|
||||||
|
- text: "Display Audit Records"
|
||||||
|
link: "/TODO/comm/[CID]/admin/audit"
|
||||||
|
permission: "Community.ShowAdmin"
|
||||||
|
- text: "Delete Community"
|
||||||
|
link: "/TODO/comm/[CID]/admin/delete"
|
||||||
|
permission: "Community.Destroy"
|
||||||
|
hazard: true
|
||||||
|
|||||||
+26
@@ -28,7 +28,9 @@ type MenuItem struct {
|
|||||||
Text string `yaml:"text"`
|
Text string `yaml:"text"`
|
||||||
Link string `yaml:"link"`
|
Link string `yaml:"link"`
|
||||||
Disabled bool `yaml:"disabled"`
|
Disabled bool `yaml:"disabled"`
|
||||||
|
Hazard bool `yaml:"hazard"`
|
||||||
Permission string `yaml:"permission"`
|
Permission string `yaml:"permission"`
|
||||||
|
Ifdef string `yaml:"ifdef"`
|
||||||
P *MenuDefinition
|
P *MenuDefinition
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,12 +67,36 @@ func (mi *MenuItem) Show(ctxt AmContext) bool {
|
|||||||
type MenuDefinition struct {
|
type MenuDefinition struct {
|
||||||
ID string `yaml:"id"`
|
ID string `yaml:"id"`
|
||||||
Title string `yaml:"title"`
|
Title string `yaml:"title"`
|
||||||
|
Subtitle string `yaml:"subtitle"`
|
||||||
PermSet string `yaml:"permSet"`
|
PermSet string `yaml:"permSet"`
|
||||||
Warning string `yaml:"warning"`
|
Warning string `yaml:"warning"`
|
||||||
Items []MenuItem `yaml:"items"`
|
Items []MenuItem `yaml:"items"`
|
||||||
Tag string
|
Tag string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterCommunity creates a copy of this menu filtered to the specified community.
|
||||||
|
func (mdef *MenuDefinition) FilterCommunity(comm *database.Community) *MenuDefinition {
|
||||||
|
newmd := MenuDefinition{
|
||||||
|
ID: mdef.ID,
|
||||||
|
Title: mdef.Title,
|
||||||
|
Subtitle: strings.ReplaceAll(mdef.Subtitle, "[CNAME]", comm.Name),
|
||||||
|
PermSet: mdef.PermSet,
|
||||||
|
Warning: mdef.Warning,
|
||||||
|
Items: make([]MenuItem, len(mdef.Items)),
|
||||||
|
Tag: mdef.Tag,
|
||||||
|
}
|
||||||
|
for i, it := range mdef.Items {
|
||||||
|
newmd.Items[i].Text = it.Text
|
||||||
|
newmd.Items[i].Link = strings.ReplaceAll(it.Link, "[CID]", comm.Alias)
|
||||||
|
newmd.Items[i].Disabled = it.Disabled
|
||||||
|
newmd.Items[i].Hazard = it.Hazard
|
||||||
|
newmd.Items[i].Permission = it.Permission
|
||||||
|
newmd.Items[i].Ifdef = it.Ifdef
|
||||||
|
newmd.Items[i].P = &newmd
|
||||||
|
}
|
||||||
|
return &newmd
|
||||||
|
}
|
||||||
|
|
||||||
// MenuDefs represents the set of all menu definitions.
|
// MenuDefs represents the set of all menu definitions.
|
||||||
type MenuDefs struct {
|
type MenuDefs struct {
|
||||||
D []MenuDefinition `yaml:"menudefs"`
|
D []MenuDefinition `yaml:"menudefs"`
|
||||||
|
|||||||
+10
-1
@@ -10,6 +10,9 @@
|
|||||||
<!-- Page Title -->
|
<!-- Page Title -->
|
||||||
<div class="mb-6">
|
<div class="mb-6">
|
||||||
<h1 class="text-blue-800 text-4xl font-bold mb-2">{{ menu.Title }}</h1>
|
<h1 class="text-blue-800 text-4xl font-bold mb-2">{{ menu.Title }}</h1>
|
||||||
|
{{ if menu.Subtitle != "" }}
|
||||||
|
<span class="text-blue-800 text-2xl font-bold ml-2">{{ menu.Subtitle }}</span>
|
||||||
|
{{ end }}
|
||||||
<hr class="border-2 border-gray-400 w-4/5 mb-4">
|
<hr class="border-2 border-gray-400 w-4/5 mb-4">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -19,14 +22,20 @@
|
|||||||
<nav class="space-y-3">
|
<nav class="space-y-3">
|
||||||
{{ ctxt := . }}
|
{{ ctxt := . }}
|
||||||
{{ range menu.Items }}
|
{{ range menu.Items }}
|
||||||
{{ if .Show(ctxt) }}
|
{{ vis := true }}
|
||||||
|
{{ if .Ifdef != "" && !defs[.Ifdef] }}{{ vis = false }}{{ end }}
|
||||||
|
{{ if vis && .Show(ctxt) }}
|
||||||
<div class="flex items-start gap-3">
|
<div class="flex items-start gap-3">
|
||||||
<span class="text-lg pt-0.5">🟣</span>
|
<span class="text-lg pt-0.5">🟣</span>
|
||||||
{{ if .Disabled }}
|
{{ if .Disabled }}
|
||||||
<span class="text-gray-500 font-medium">{{ .Text }}</span>
|
<span class="text-gray-500 font-medium">{{ .Text }}</span>
|
||||||
|
{{ else }}
|
||||||
|
{{ if .Hazard }}
|
||||||
|
<a href="{{ .Link }}" class="text-red-700 hover:text-red-900 font-medium">⚠️ {{ .Text }}</a>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<a href="{{ .Link }}" class="text-blue-700 hover:text-blue-900 font-medium">{{ .Text }}</a>
|
<a href="{{ .Link }}" class="text-blue-700 hover:text-blue-900 font-medium">{{ .Text }}</a>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .IsMember() && !.IsMemberLocked() }}
|
{{ if .IsMember() && !.IsMemberLocked() }}
|
||||||
<div class="mb-1"> </div>
|
<div class="mb-1"><a href="/TODO/comm/{{ comm.Alias }}/unjoin" class="text-red-700 hover:text-red-900">⚠️ Unjoin</a></div>
|
||||||
<div class="mb-1"><a href="/TODO/comm/{{ comm.Alias }}/unjoin" class="text-blue-700 hover:text-blue-900">Unjoin</a></div>
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user