From 0dd66709d98ea83f0239c126353d93661e16b0cd Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Sun, 25 Jan 2026 22:47:28 -0700 Subject: [PATCH] start point of hotlist support (untested) --- conference.go | 2 +- database/hotlist.go | 49 ++++++++++++++++++++++++++++++++++++++++- database/user.go | 11 +++++---- docs/MISSINGFUNCS.md | 2 +- top.go | 44 ++++++++++++++++++++++++++++++++---- ui/views/sb_ftrconf.jet | 26 ++++++++++++++-------- 6 files changed, 114 insertions(+), 20 deletions(-) diff --git a/conference.go b/conference.go index 65b569b..c90ebe9 100644 --- a/conference.go +++ b/conference.go @@ -119,7 +119,7 @@ func Topics(ctxt ui.AmContext) (string, any, error) { ctxt.VarMap().Set("conferenceName", conf.Name) ctxt.VarMap().Set("urlBack", fmt.Sprintf("/comm/%s/conf", comm.Alias)) ctxt.VarMap().Set("urlStem", urlStem) - ctxt.VarMap().Set("permalink", "TODO") + ctxt.VarMap().Set("permalink", fmt.Sprintf("/go/%s!%s", comm.Alias, ctxt.GetScratch("currentAlias"))) ctxt.VarMap().Set("view", view) ctxt.VarMap().Set("sort", sort) ctxt.VarMap().Set("topics", topics) diff --git a/database/hotlist.go b/database/hotlist.go index 0da95db..187887a 100644 --- a/database/hotlist.go +++ b/database/hotlist.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 @@ -9,9 +9,56 @@ // The database package contains database management and storage logic. package database +import "context" + +// ConferenceHotlist represents a user's conference hotlist. type ConferenceHotlist struct { Uid int32 `db:"uid"` Sequence int16 `db:"sequence"` CommId int32 `db:"commid"` ConfId int32 `db:"confid"` } + +// Community gets the community pointer from the hotlist. +func (h *ConferenceHotlist) Community(ctx context.Context) (*Community, error) { + return AmGetCommunity(ctx, h.CommId) +} + +// Conference gets the conference pointer from the hotlist. +func (h *ConferenceHotlist) Conference(ctx context.Context) (*Conference, error) { + return AmGetConference(ctx, h.ConfId) +} + +// AmGetConferenceHotlist gets the conference hotlist for a user. +func AmGetConferenceHotlist(ctx context.Context, u *User) ([]ConferenceHotlist, error) { + var rc []ConferenceHotlist + err := amdb.SelectContext(ctx, &rc, "SELECT * FROM confhotlist WHERE uid = ? ORDER BY sequence", u.Uid) + return rc, err +} + +// AmCopyConferenceHotlist copies the conference hotlist from one user to another. +func AmCopyConferenceHotlist(ctx context.Context, from, to *User) error { + hotlist, err := AmGetConferenceHotlist(ctx, from) + if err != nil { + return err + } + + success := false + tx := amdb.MustBegin() + defer func() { + if !success { + tx.Rollback() + } + }() + for _, hl := range hotlist { + if _, err = tx.ExecContext(ctx, "INSERT INTO confhotlist (uid, sequence, commid, confid) VALUES (?, ?, ?, ?)", + to.Uid, hl.Sequence, hl.CommId, hl.ConfId); err != nil { + return err + } + } + if err = tx.Commit(); err != nil { + return err + } + success = true + return nil +} diff --git a/database/user.go b/database/user.go index dc2edd4..981583e 100644 --- a/database/user.go +++ b/database/user.go @@ -680,7 +680,7 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi defer func() { AmStoreAudit(ar) }() - anon, _ := getAnonUserID(ctx) + anon, _ := AmGetAnonUser(ctx) success := false tx := amdb.MustBegin() defer func() { @@ -728,7 +728,7 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi // add user properties props := make([]UserProperties, 0) - if err = tx.SelectContext(ctx, &props, "SELECT * FROM propuser WHERE uid = ?", anon); err != nil { + if err = tx.SelectContext(ctx, &props, "SELECT * FROM propuser WHERE uid = ?", anon.Uid); err != nil { return nil, err } for _, p := range props { @@ -739,7 +739,7 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi } // add user sideboxes - if err = copySideboxes(ctx, tx, user.Uid, anon); err != nil { + if err = copySideboxes(ctx, tx, user.Uid, anon.Uid); err != nil { return nil, err } @@ -756,7 +756,10 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi return nil, err } - // TODO: copy conference hotlists + // copy conference hotlists + if err = AmCopyConferenceHotlist(ctx, anon, user); err != nil { + return nil, err + } // operation was a success - add an audit record ar = AmNewAudit(AuditAccountCreated, user.Uid, remoteIP) diff --git a/docs/MISSINGFUNCS.md b/docs/MISSINGFUNCS.md index 62df982..f8d8ddf 100644 --- a/docs/MISSINGFUNCS.md +++ b/docs/MISSINGFUNCS.md @@ -1,6 +1,6 @@ # TODOs list: -- Topics list: Set up Conference permalink +- ~~Topics list: Set up Conference permalink~~ - Send out E-mails to topic subscribers when a post is made - Error handling: shift titles and templates for different error codes - Find Posts diff --git a/top.go b/top.go index eb2e585..41b4714 100644 --- a/top.go +++ b/top.go @@ -22,6 +22,7 @@ import ( // RenderedSideboxItem is an item for display inside a rendered sidebox. type RenderedSideboxItem struct { Text string + Text2 string Link *string Flags map[string]bool } @@ -95,15 +96,50 @@ func buildCommunitiesSidebox(ctxt ui.AmContext, uid int32, out *RenderedSidebox, /* buildFeaturedConferences creates the data for the "Featured Conferences" sidebox. * Parameters: + * ctxt - AmContext for the operation. * uid - UID of the user rendering the page. * out - The RenderedSidebox to be built. * in - The sidebox data from the database. * Returns: * Standard Go error status. */ -func buildFeaturedConferences(uid int32, out *RenderedSidebox, in *database.Sidebox) error { - out.TemplateName = "sb_ftrconf.jet" - return nil +func buildFeaturedConferences(ctxt ui.AmContext, uid int32, out *RenderedSidebox, in *database.Sidebox) error { + user, err := database.AmGetUser(ctxt.Ctx(), uid) + if err == nil { + if user.IsAnon { + out.Title = "Featured Conferences" + } else { + out.Title = "Your Conference Hotlist" + } + var hl []database.ConferenceHotlist + hl, err := database.AmGetConferenceHotlist(ctxt.Ctx(), user) + if err == nil { + out.Items = make([]RenderedSideboxItem, len(hl)) + for i, h := range hl { + comm, err := h.Community(ctxt.Ctx()) + if err != nil { + break + } + conf, err := h.Conference(ctxt.Ctx()) + if err != nil { + break + } + alias, err := conf.Aliases(ctxt.Ctx()) + if err != nil { + break + } + out.Items[i].Text = conf.Name + out.Items[i].Text2 = comm.Name + lk := fmt.Sprintf("/comm/%s/conf/%s", comm.Alias, alias[0]) + out.Items[i].Link = &lk + out.Items[i].Flags = make(map[string]bool) + // TODO: add "New" indicator + } + out.Flags = make(map[string]bool) + out.TemplateName = "sb_ftrconf.jet" + } + } + return err } /* buildUsersOnline creates the data for the "Users Online" sidebox. @@ -158,7 +194,7 @@ func buildRenderedSidebox(ctxt ui.AmContext, uid int32, out *RenderedSidebox, in case 1: return buildCommunitiesSidebox(ctxt, uid, out, in) case 2: - return buildFeaturedConferences(uid, out, in) + return buildFeaturedConferences(ctxt, uid, out, in) case 3: return buildUsersOnline(uid, out, in) default: diff --git a/ui/views/sb_ftrconf.jet b/ui/views/sb_ftrconf.jet index 04a9822..7067364 100644 --- a/ui/views/sb_ftrconf.jet +++ b/ui/views/sb_ftrconf.jet @@ -6,19 +6,27 @@ * 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/. *} - + +{{ sb := .GetScratch("__sidebox") }}
-

Featured Conferences:

+

{{ sb.Title }}:

-
- 🟣 -
- General Discussion - (La Piazza) -
+
+ {{ if len(sb.Items) > 0 }} + {{ range i, item := sb.Items }} +
+ 🟣 +
+ {{ item.Text }} + ({{ item.Text2 }}) +
+
+ {{ end }} + {{ else }} +
No conferences in hotlist.
+ {{ end }}