From c7e43b539bfc407eccbdaaf9749a63eb4b58c875 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Mon, 2 Feb 2026 15:58:08 -0700 Subject: [PATCH] landed "change conference information" and fixed a bug in AmGetPublishedPosts --- conferenceadmin.go | 56 ++++++++++++++++++++++++++++++++++++++++++ database/conference.go | 36 +++++++++++++++++++++++++++ database/post.go | 3 +++ main.go | 1 + 4 files changed, 96 insertions(+) diff --git a/conferenceadmin.go b/conferenceadmin.go index 938cacb..ae4ab6b 100644 --- a/conferenceadmin.go +++ b/conferenceadmin.go @@ -11,10 +11,12 @@ package main import ( + "fmt" "net/http" "git.erbosoft.com/amy/amsterdam/database" "git.erbosoft.com/amy/amsterdam/ui" + "git.erbosoft.com/amy/amsterdam/util" ) /* EditConferenceForm displays the dialog for editing the conference properties. @@ -65,3 +67,57 @@ func EditConferenceForm(ctxt ui.AmContext) (string, any, error) { dlg.Field("pic_in_post").SetChecked(flags.Get(database.ConferenceFlagPicturesInPosts)) return dlg.Render(ctxt) } + +/* EditConference saves the conference properties being edited. + * 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 EditConference(ctxt ui.AmContext) (string, any, error) { + comm := ctxt.CurrentCommunity() + conf := ctxt.GetScratch("currentConference").(*database.Conference) + myLevel := ctxt.GetScratch("levelInConference").(uint16) + if !conf.TestPermission("Conference.Change", myLevel) { + ctxt.SetRC(http.StatusForbidden) + return ui.ErrorPage(ctxt, ENOPERM) + } + + dlg, err := ui.AmLoadDialog("edit_conference") + if err != nil { + return ui.ErrorPage(ctxt, err) + } + button := dlg.WhichButton(ctxt) + if button == "cancel" { + return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil + } else if button != "update" { + dlg.SetCommunity(comm) + dlg.SetConference(conf, ctxt.GetScratch("currentAlias").(string)) + return dlg.RenderError(ctxt, "invalid button pressed") + } + + dlg.LoadFromForm(ctxt) + if err = dlg.Validate(); err == nil { + if err = conf.SetInfo(ctxt.Ctx(), dlg.Field("name").Value, dlg.Field("descr").Value, dlg.Field("read_lvl").GetLevel(), dlg.Field("post_lvl").GetLevel(), + dlg.Field("create_lvl").GetLevel(), dlg.Field("hide_lvl").GetLevel(), dlg.Field("nuke_lvl").GetLevel(), dlg.Field("change_lvl").GetLevel(), + dlg.Field("delete_lvl").GetLevel()); err == nil { + if err = conf.SetHiddenInList(ctxt.Ctx(), comm, dlg.Field("hide").IsChecked()); err == nil { + var flags *util.OptionSet + flags, err = conf.Flags(ctxt.Ctx()) + if err == nil { + flags.Set(database.ConferenceFlagPicturesInPosts, dlg.Field("pic_in_post").IsChecked()) + err = conf.SaveFlags(ctxt.Ctx(), flags) + } + } + } + } + if err != nil { + dlg.SetCommunity(comm) + dlg.SetConference(conf, ctxt.GetScratch("currentAlias").(string)) + return dlg.RenderError(ctxt, err.Error()) + } + + return "redirect", fmt.Sprintf("/comm/%s/conf/%s/manage", comm.Alias, ctxt.GetScratch("currentAlias")), nil +} diff --git a/database/conference.go b/database/conference.go index 9725471..3ce5700 100644 --- a/database/conference.go +++ b/database/conference.go @@ -186,6 +186,12 @@ func (c *Conference) HiddenInList(ctx context.Context, comm *Community) (bool, e return false, err } +// SetHiddenInList sets whether or not this conference is hidden in the community's conference list. +func (c *Conference) SetHiddenInList(ctx context.Context, comm *Community, flag bool) error { + _, err := amdb.ExecContext(ctx, "UPDATE commtoconf SET hide_list = ? WHERE commid = ? AND confid = ?", flag, comm.Id, c.ConfId) + return err +} + // ContainedBy returns the communities that contain this conference. func (c *Conference) ContainedBy(ctx context.Context) ([]*Community, error) { rs, err := amdb.QueryContext(ctx, "SELECT commid FROM commtoconf WHERE confid = ?", c.ConfId) @@ -330,6 +336,36 @@ func (c *Conference) Link(ctx context.Context, scope string) (string, error) { return "", errors.New("invalid scope") } +// SetInfo sets the name, pseud, and security levels on a conference. +func (c *Conference) SetInfo(ctx context.Context, name, descr string, read_lvl, post_lvl, create_lvl, hide_lvl, nuke_lvl, change_lvl, delete_lvl uint16) error { + c.Mutex.Lock() + defer c.Mutex.Unlock() + _, err := amdb.ExecContext(ctx, `UPDATE confs SET name = ?, descr = ?, read_lvl = ?, post_lvl = ?, create_lvl = ?, + hide_lvl = ?, nuke_lvl = ?, change_lvl = ?, delete_lvl = ?, lastupdate = NOW() WHERE confid = ?`, name, descr, read_lvl, post_lvl, + create_lvl, hide_lvl, nuke_lvl, change_lvl, delete_lvl, c.ConfId) + if err == nil { + var tmp []Conference + err := amdb.SelectContext(ctx, &tmp, "SELECT * FROM confs WHERE confid = ?", c.ConfId) + if err == nil { + if len(tmp) != 1 { + err = errors.New("internal error rereading conference") + } else { + c.Name = tmp[0].Name + c.Description = tmp[0].Description + c.ReadLevel = tmp[0].ReadLevel + c.PostLevel = tmp[0].PostLevel + c.CreateLevel = tmp[0].CreateLevel + c.HideLevel = tmp[0].HideLevel + c.NukeLevel = tmp[0].NukeLevel + c.ChangeLevel = tmp[0].ChangeLevel + c.DeleteLevel = tmp[0].DeleteLevel + c.LastUpdate = tmp[0].LastUpdate + } + } + } + return err +} + // DefaultPseud returns the default pseud for a user in the conference. func (c *Conference) DefaultPseud(ctx context.Context, u *User) (string, error) { settings, err := c.Settings(ctx, u) diff --git a/database/post.go b/database/post.go index 7adc9fe..3805cd4 100644 --- a/database/post.go +++ b/database/post.go @@ -682,6 +682,9 @@ func AmGetPublishedPosts(ctx context.Context) ([]*PostHeader, error) { } i++ } + if i == 0 { // no published posts, short-circuit response + return make([]*PostHeader, 0), nil + } if i < int(gv.FrontPagePosts) { pids = pids[:i] // truncate if we have fewer posts than spaces } diff --git a/main.go b/main.go index b02dd3b..f908c94 100644 --- a/main.go +++ b/main.go @@ -111,6 +111,7 @@ func setupEcho() *echo.Echo { confGroup.POST("/pseud", ui.AmWrap(SetPseud)) confGroup.GET("/fixseen", ui.AmWrap(ConfFixseen)) confGroup.GET("/edit", ui.AmWrap(EditConferenceForm)) + confGroup.POST("/edit", ui.AmWrap(EditConference)) confGroup.GET("/hotlist", ui.AmWrap(AddToHotlist)) confGroup.GET("/invite", ui.AmWrap(InviteToConference)) confGroup.GET("/r/:topic", ui.AmWrap(ReadPosts), ui.SetTopic)