resolve bugs in community profile display

This commit is contained in:
2025-10-17 11:53:30 -06:00
parent 65c739dc57
commit 137bf35a8b
9 changed files with 40 additions and 17 deletions
+1
View File
@@ -29,6 +29,7 @@ const AMSTERDAM_COPYRIGHT = "2025"
// AmCLI is the command-line interface arguments structure. // AmCLI is the command-line interface arguments structure.
type AmCLI struct { type AmCLI struct {
ConfigFile string `arg:"-C,--config" help:"Location of the configuration file."` ConfigFile string `arg:"-C,--config" help:"Location of the configuration file."`
DebugPanic bool `arg:"--debug-panic" help:"Development Only - disable Echo panic recovery"`
} }
// CommandLine is the command-line arguments passed to Amsterdam. // CommandLine is the command-line arguments passed to Amsterdam.
+5
View File
@@ -25,6 +25,7 @@ import (
"github.com/labstack/echo-contrib/session" "github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware" "github.com/labstack/echo/v4/middleware"
log "github.com/sirupsen/logrus"
) )
// setupEcho creates, configures, and returns a new Echo instance. // setupEcho creates, configures, and returns a new Echo instance.
@@ -32,7 +33,11 @@ func setupEcho() *echo.Echo {
e := echo.New() e := echo.New()
e.Logger = &EchoLogrusAdapter{} e.Logger = &EchoLogrusAdapter{}
e.Renderer = &ui.TemplateRenderer{} e.Renderer = &ui.TemplateRenderer{}
if !config.CommandLine.DebugPanic {
e.Use(middleware.Recover()) e.Use(middleware.Recover())
} else {
log.Warn("WARNING: --debug-panic in effect - DO NOT use this in production!")
}
e.Use(LogrusMiddleware) e.Use(LogrusMiddleware)
e.Use(session.Middleware(ui.SessionStore)) e.Use(session.Middleware(ui.SessionStore))
+2 -2
View File
@@ -986,7 +986,7 @@ INSERT INTO communities (commid, createdate, read_lvl, write_lvl, create_lvl, de
host_uid, catid, membersonly, init_ftr, commname, language, synopsis, rules, alias) host_uid, catid, membersonly, init_ftr, commname, language, synopsis, rules, alias)
VALUES (2, '2000-12-01 00:00:00', 100, 58000, 58000, 65500, 500, 4, 2, 0, 1, 0, 'Coffeehouse', 'en-US', VALUES (2, '2000-12-01 00:00:00', 100, 58000, 58000, 65500, 500, 4, 2, 0, 1, 0, 'Coffeehouse', 'en-US',
'A gathering place for news and information for all Amsterdam users.', 'A gathering place for news and information for all Amsterdam users.',
'Like the man said, do unto others as you would have them do unto you.', 'Piazza'); 'Like the man said, do unto others as you would have them do unto you.', 'Coffeehouse');
INSERT INTO contacts (contactid, locality, country, owner_uid, owner_commid) INSERT INTO contacts (contactid, locality, country, owner_uid, owner_commid)
VALUES (4, 'Anywhere', 'US', 2, 2); VALUES (4, 'Anywhere', 'US', 2, 2);
INSERT INTO propcomm (cid, ndx, data) VALUES (2, 0, ''); INSERT INTO propcomm (cid, ndx, data) VALUES (2, 0, '');
@@ -1001,7 +1001,7 @@ INSERT INTO commftrs (commid, ftr_code)
INSERT INTO commmember (commid, uid, granted_lvl, locked, hidden) INSERT INTO commmember (commid, uid, granted_lvl, locked, hidden)
VALUES (2, 1, 100, 1, 1); VALUES (2, 1, 100, 1, 1);
# Make the 'Administrator' user the host of La Piazza. # Make the 'Administrator' user the host of Coffeehouse.
INSERT INTO commmember (commid, uid, granted_lvl, locked) INSERT INTO commmember (commid, uid, granted_lvl, locked)
VALUES (2, 2, 58500, 1); VALUES (2, 2, 58500, 1);
+10 -1
View File
@@ -43,6 +43,7 @@ type AmContext interface {
Globals() *database.Globals Globals() *database.Globals
GlobalFlags() *util.OptionSet GlobalFlags() *util.OptionSet
IsMember() bool IsMember() bool
IsMemberLocked() bool
LeftMenu() string LeftMenu() string
RC() int RC() int
OutputType() string OutputType() string
@@ -79,6 +80,7 @@ type amContext struct {
effectiveLevel uint16 effectiveLevel uint16
community *database.Community community *database.Community
isMember bool isMember bool
isMemberLocked bool
} }
// ClearLoginCookie overwrites and removes the login cookie. // ClearLoginCookie overwrites and removes the login cookie.
@@ -186,6 +188,11 @@ func (c *amContext) IsMember() bool {
return c.isMember return c.isMember
} }
// IsMemberLocked returns true if the user is a "locked" member of the currentr community (cannot unjoin).
func (c *amContext) IsMemberLocked() bool {
return c.isMemberLocked
}
// LeftMenu returns the current left menu selector. // LeftMenu returns the current left menu selector.
func (c *amContext) LeftMenu() string { func (c *amContext) LeftMenu() string {
return c.session.Values["leftMenu"].(string) return c.session.Values["leftMenu"].(string)
@@ -272,12 +279,13 @@ func (c *amContext) SetCommunityContext(param string) error {
if err != nil { if err != nil {
return err return err
} }
mbr, _, level, err := comm.Membership(c.CurrentUser()) mbr, lock, level, err := comm.Membership(c.CurrentUser())
if err != nil { if err != nil {
return err return err
} }
c.community = comm c.community = comm
c.isMember = mbr c.isMember = mbr
c.isMemberLocked = lock
if level > c.effectiveLevel { if level > c.effectiveLevel {
c.effectiveLevel = level c.effectiveLevel = level
} }
@@ -454,6 +462,7 @@ func contextRecycler(incoming chan *amContext, done chan bool) {
c.effectiveLevel = 0 c.effectiveLevel = 0
c.community = nil c.community = nil
c.isMember = false c.isMember = false
c.isMemberLocked = false
freeContext.Put(c) freeContext.Put(c)
} }
done <- true done <- true
+4
View File
@@ -14,6 +14,7 @@ import (
"bytes" "bytes"
"embed" "embed"
"errors" "errors"
"fmt"
"image" "image"
"image/gif" "image/gif"
"image/jpeg" "image/jpeg"
@@ -85,6 +86,9 @@ func AmServeImage(ctxt AmContext) (string, any, error) {
} }
} }
ctxt.SetRC(http.StatusNotFound) ctxt.SetRC(http.StatusNotFound)
if err == nil {
err = fmt.Errorf("image not found: %s", ctxt.URLPath())
}
return ErrorPage(ctxt, err) return ErrorPage(ctxt, err)
} }
+8 -7
View File
@@ -135,10 +135,18 @@ func AmBuildCommunityMenu(comm *database.Community) (*MenuDefinition, error) {
return a.LinkSequence - b.LinkSequence return a.LinkSequence - b.LinkSequence
}) })
mia := make([]MenuItem, len(sdef)) mia := make([]MenuItem, len(sdef))
md := MenuDefinition{
ID: "community",
Title: comm.Name,
PermSet: "community",
Tag: "community",
Items: mia,
}
for i, sd := range sdef { for i, sd := range sdef {
mia[i].Text = sd.Title mia[i].Text = sd.Title
mia[i].Link = strings.ReplaceAll(sd.Link, "[CID]", comm.Alias) mia[i].Link = strings.ReplaceAll(sd.Link, "[CID]", comm.Alias)
mia[i].Disabled = false mia[i].Disabled = false
mia[i].P = &md
if sd.RequirePermission == "" { if sd.RequirePermission == "" {
if sd.RequireRole == "" { if sd.RequireRole == "" {
mia[i].Permission = "" mia[i].Permission = ""
@@ -156,13 +164,6 @@ func AmBuildCommunityMenu(comm *database.Community) (*MenuDefinition, error) {
mia[i].Permission = fmt.Sprintf("%d", v1) mia[i].Permission = fmt.Sprintf("%d", v1)
} }
} }
md := MenuDefinition{
ID: "community",
Title: comm.Name,
PermSet: "community",
Items: mia,
Tag: "community",
}
menuCache.Add(comm.Id, &md) menuCache.Add(comm.Id, &md)
return &md, nil return &md, nil
} }
+3
View File
@@ -69,6 +69,9 @@ func sendPageData(ctxt echo.Context, amctxt AmContext, command string, data any)
* Standard Go error status. * Standard Go error status.
*/ */
func ErrorPage(ctxt AmContext, input_err error) (string, any, error) { func ErrorPage(ctxt AmContext, input_err error) (string, any, error) {
if input_err == nil {
log.Error("ErrorPage called with nil input error, WTF?")
}
ctxt.VarMap().Set("amsterdam_pageTitle", "Internal Server Error") ctxt.VarMap().Set("amsterdam_pageTitle", "Internal Server Error")
ctxt.VarMap().Set("error", input_err.Error()) ctxt.VarMap().Set("error", input_err.Error())
return "framed_template", "error.jet", nil return "framed_template", "error.jet", nil
+2 -2
View File
@@ -19,7 +19,7 @@
<!-- Left Column: Image and Metadata --> <!-- Left Column: Image and Metadata -->
<div class="flex-shrink-0 w-32"> <div class="flex-shrink-0 w-32">
<div class="border-2 border-gray-300 rounded mb-4"> <div class="border-2 border-gray-300 rounded mb-4">
<img src="/img/static/default-community.jpg" <img src="/img/builtin/default-community.jpg"
alt="{{ commName}} community logo" class="w-full h-auto"> alt="{{ commName}} community logo" class="w-full h-auto">
</div> </div>
<div class="text-xs text-gray-700 space-y-2 mb-4"> <div class="text-xs text-gray-700 space-y-2 mb-4">
@@ -79,7 +79,7 @@
<!-- Host --> <!-- Host -->
<div> <div>
<strong>Host:</strong> <strong>Host:</strong>
<a href="/users/{{ hostName }}" class="text-blue-700 hover:text-blue-900">{{ hostName }}</a> <a href="/user/{{ hostName }}" class="text-blue-700 hover:text-blue-900">{{ hostName }}</a>
</div> </div>
<!-- Location --> <!-- Location -->
+3 -3
View File
@@ -20,12 +20,12 @@
{{ if .Disabled }} {{ if .Disabled }}
<div class="text-gray-500 mb-1">{{ .Text }}</div> <div class="text-gray-500 mb-1">{{ .Text }}</div>
{{ else }} {{ else }}
<a href="{{ .Link }}" class="text-blue-700 hover:text-blue-900">{{ .Text }}</a> <div class="mb-1"><a href="{{ .Link }}" class="text-blue-700 hover:text-blue-900">{{ .Text }}</a></div>
{{ end }} {{ end }}
{{ end }} {{ end }}
{{ end }} {{ end }}
{{ if .IsMember() }} {{ if .IsMember() && !.IsMemberLocked() }}
<div class="mb-1">&nbsp;</div> <div class="mb-1">&nbsp;</div>
<div class="mb-1"><a href="/TODO/comm/{{ comm.Alias }}/unjoin">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>