start point of hotlist support (untested)

This commit is contained in:
2026-01-25 22:47:28 -07:00
parent c5b2c3d64b
commit 0dd66709d9
6 changed files with 114 additions and 20 deletions
+1 -1
View File
@@ -119,7 +119,7 @@ func Topics(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("conferenceName", conf.Name) ctxt.VarMap().Set("conferenceName", conf.Name)
ctxt.VarMap().Set("urlBack", fmt.Sprintf("/comm/%s/conf", comm.Alias)) ctxt.VarMap().Set("urlBack", fmt.Sprintf("/comm/%s/conf", comm.Alias))
ctxt.VarMap().Set("urlStem", urlStem) 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("view", view)
ctxt.VarMap().Set("sort", sort) ctxt.VarMap().Set("sort", sort)
ctxt.VarMap().Set("topics", topics) ctxt.VarMap().Set("topics", topics)
+48 -1
View File
@@ -1,6 +1,6 @@
/* /*
* Amsterdam Web Communities System * 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 * 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 * 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. // The database package contains database management and storage logic.
package database package database
import "context"
// ConferenceHotlist represents a user's conference hotlist.
type ConferenceHotlist struct { type ConferenceHotlist struct {
Uid int32 `db:"uid"` Uid int32 `db:"uid"`
Sequence int16 `db:"sequence"` Sequence int16 `db:"sequence"`
CommId int32 `db:"commid"` CommId int32 `db:"commid"`
ConfId int32 `db:"confid"` 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
}
+7 -4
View File
@@ -680,7 +680,7 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi
defer func() { defer func() {
AmStoreAudit(ar) AmStoreAudit(ar)
}() }()
anon, _ := getAnonUserID(ctx) anon, _ := AmGetAnonUser(ctx)
success := false success := false
tx := amdb.MustBegin() tx := amdb.MustBegin()
defer func() { defer func() {
@@ -728,7 +728,7 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi
// add user properties // add user properties
props := make([]UserProperties, 0) 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 return nil, err
} }
for _, p := range props { for _, p := range props {
@@ -739,7 +739,7 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi
} }
// add user sideboxes // 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 return nil, err
} }
@@ -756,7 +756,10 @@ func AmCreateNewUser(ctx context.Context, username string, password string, remi
return nil, err 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 // operation was a success - add an audit record
ar = AmNewAudit(AuditAccountCreated, user.Uid, remoteIP) ar = AmNewAudit(AuditAccountCreated, user.Uid, remoteIP)
+1 -1
View File
@@ -1,6 +1,6 @@
# TODOs list: # 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 - Send out E-mails to topic subscribers when a post is made
- Error handling: shift titles and templates for different error codes - Error handling: shift titles and templates for different error codes
- Find Posts - Find Posts
+40 -4
View File
@@ -22,6 +22,7 @@ import (
// RenderedSideboxItem is an item for display inside a rendered sidebox. // RenderedSideboxItem is an item for display inside a rendered sidebox.
type RenderedSideboxItem struct { type RenderedSideboxItem struct {
Text string Text string
Text2 string
Link *string Link *string
Flags map[string]bool 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. /* buildFeaturedConferences creates the data for the "Featured Conferences" sidebox.
* Parameters: * Parameters:
* ctxt - AmContext for the operation.
* uid - UID of the user rendering the page. * uid - UID of the user rendering the page.
* out - The RenderedSidebox to be built. * out - The RenderedSidebox to be built.
* in - The sidebox data from the database. * in - The sidebox data from the database.
* Returns: * Returns:
* Standard Go error status. * Standard Go error status.
*/ */
func buildFeaturedConferences(uid int32, out *RenderedSidebox, in *database.Sidebox) error { func buildFeaturedConferences(ctxt ui.AmContext, uid int32, out *RenderedSidebox, in *database.Sidebox) error {
out.TemplateName = "sb_ftrconf.jet" user, err := database.AmGetUser(ctxt.Ctx(), uid)
return nil 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. /* 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: case 1:
return buildCommunitiesSidebox(ctxt, uid, out, in) return buildCommunitiesSidebox(ctxt, uid, out, in)
case 2: case 2:
return buildFeaturedConferences(uid, out, in) return buildFeaturedConferences(ctxt, uid, out, in)
case 3: case 3:
return buildUsersOnline(uid, out, in) return buildUsersOnline(uid, out, in)
default: default:
+17 -9
View File
@@ -6,19 +6,27 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*} *}
<!-- Featured Conferences --> <!-- Conference Hotlist sidebox -->
{{ sb := .GetScratch("__sidebox") }}
<div class="mb-4"> <div class="mb-4">
<div class="bg-blue-600 px-2 py-1 rounded-t"> <div class="bg-blue-600 px-2 py-1 rounded-t">
<h3 class="text-white font-bold text-base">Featured Conferences:</h3> <h3 class="text-white font-bold text-base">{{ sb.Title }}:</h3>
</div> </div>
<div class="bg-blue-400 px-2 py-2 rounded-b"> <div class="bg-blue-400 px-2 py-2 rounded-b">
<div class="flex items-center"> <div class="space-y-2">
<span class="mr-2">🟣</span> {{ if len(sb.Items) > 0 }}
<div class="text-sm"> {{ range i, item := sb.Items }}
<a href="http://necrovenice:8080/venice/conf/topics.js.vs?sig=2&conf=2" <div class="flex items-center">
class="text-blue-700 hover:text-blue-900 font-bold">General Discussion</a> <span class="mr-2">🟣</span>
<span class="text-black"> (La Piazza)</span> <div class="text-sm">
</div> <a href="{{ item.Link }}" class="text-blue-700 hover:text-blue-900 font-bold">{{ item.Text }}</a>
<span class="text-black"> ({{ item.Text2 }})</span>
</div>
</div>
{{ end }}
{{ else }}
<div class="text-small">No conferences in hotlist.</div>
{{ end }}
</div> </div>
</div> </div>
</div> </div>