made the category hierarchy on Find Communities "live"

This commit is contained in:
2025-10-19 21:48:37 -06:00
parent 89da7e8456
commit 71da667361
3 changed files with 118 additions and 91 deletions
+28 -2
View File
@@ -11,6 +11,8 @@ package database
import (
"errors"
"slices"
"strings"
"sync"
)
@@ -19,8 +21,8 @@ type Category struct {
CatId int32 `db:"catid"`
Parent int32 `db:"parent"`
SymLink int32 `db:"symlink"`
HideDirectory int32 `db:"hide_dir"`
HideSearch int32 `db:"hide_search"`
HideDirectory bool `db:"hide_dir"`
HideSearch bool `db:"hide_search"`
Name string `db:"name"`
}
@@ -113,3 +115,27 @@ func AmGetCategoryHierarchy(catid int32) ([]*Category, error) {
}
return rc, nil
}
/* AmGetSubCategories returns a list of all subcategories of the given category ID.
* Parameters:
* catid - The parent category ID to use. May be -1 to return all "top level" categories.
* Returns:
* List of subcategories of this category.
* Standard Go error status.
*/
func AmGetSubCategories(catid int32) ([]*Category, error) {
err := loadCategories()
if err != nil {
return nil, err
}
rc := make([]*Category, 0)
for i, cat := range allCategories {
if catid == cat.Parent {
rc = append(rc, &(allCategories[i]))
}
}
slices.SortFunc(rc, func(a, b *Category) int {
return strings.Compare(a.Name, b.Name)
})
return rc, nil
}
+53 -3
View File
@@ -9,7 +9,53 @@
// Package main contains the high-level Amsterdam logic.
package main
import "git.erbosoft.com/amy/amsterdam/ui"
import (
"strconv"
"git.erbosoft.com/amy/amsterdam/database"
"git.erbosoft.com/amy/amsterdam/ui"
)
// loadCategoryInformation loads the current category information to the context.
func loadCategoryInformation(ctxt ui.AmContext) error {
u := ctxt.CurrentUser()
catid := int32(-1)
p := ctxt.Parameter("catid")
if p != "" {
v, err := strconv.Atoi(p)
if err != nil {
return err
}
catid = int32(v)
} else if ctxt.IsSession("find.catid") {
x := ctxt.GetSession("find.catid")
if xx, ok := x.(int32); ok {
catid = xx
}
}
if catid > -1 {
cat, err := database.AmGetCategory(catid) // this step also resolves symlinks
if err != nil {
return err
}
catid = cat.CatId
}
ctxt.SetSession("find.catid", catid)
ctxt.VarMap().Set("catid", catid)
ctxt.VarMap().Set("showHiddenCat", database.AmTestPermission("Global.ShowHiddenCategories", u.BaseLevel))
hier, err := database.AmGetCategoryHierarchy(catid)
if err != nil {
return err
}
ctxt.VarMap().Set("catHierarchy", hier)
subs, err := database.AmGetSubCategories(catid)
if err != nil {
return err
}
ctxt.VarMap().Set("catSubs", subs)
// TODO: set matching communities as well
return nil
}
/* FindPage renders the Amsterdam "Find" page.
* Parameters:
@@ -33,11 +79,17 @@ func FindPage(ctxt ui.AmContext) (string, any, error) {
if mode == "" {
mode = "COM"
}
ctxt.SetSession("find.mode", mode)
ctxt.VarMap().Set("mode", mode)
switch mode {
case "COM":
ctxt.VarMap().Set("field", "name")
ctxt.VarMap().Set("oper", "st")
ctxt.VarMap().Set("term", "")
err := loadCategoryInformation(ctxt)
if err != nil {
return ui.ErrorPage(ctxt, err)
}
case "USR":
ctxt.VarMap().Set("field", "name")
ctxt.VarMap().Set("oper", "st")
@@ -49,9 +101,7 @@ func FindPage(ctxt ui.AmContext) (string, any, error) {
ctxt.VarMap().Set("term", "")
}
ctxt.VarMap().Set("mode", mode)
ctxt.VarMap().Set("amsterdam_pageTitle", "Find")
ctxt.SetLeftMenu("top")
ctxt.SetSession("find.mode", mode)
return "framed_template", "find.jet", nil
}
+37 -86
View File
@@ -11,7 +11,7 @@
<div class="mb-6">
<div class="flex items-baseline gap-2">
<h1 class="text-blue-800 text-4xl font-bold">Find:</h1>
<nav class="text-blue-800 text-lg">
<nav class="text-blue-800 text-2xl">
{{ if mode == "COM" }}
<span class="font-bold">Communities</span>
{{ else }}
@@ -45,6 +45,9 @@
<form method="POST" action="/find">
<input type="hidden" name="mode" value="{{ mode }}">
<input type="hidden" name="ofs" value="0">
{{ if mode == "COM" }}
<input type="hidden" name="catid" value="{{ catid }}">
{{ end }}
<div class="bg-gray-50 p-6 rounded-lg">
{{ if mode == "COM" }}
@@ -140,94 +143,42 @@
<div class="max-w-3xl">
<hr class="border-gray-400 mb-4">
<h2 class="text-lg font-bold text-black mb-4">Category: Top</h2>
<h2 class="text-lg font-bold text-black mb-4">
Category:
{{ if catid == -1 }}
Top
{{ else }}
<a href="/find?mode=COM&catid=-1" class="text-blue-700 hover:text-blue-900 font-bold">Top</a>
{{ end }}
{{ last := len(catHierarchy) - 1 }}
{{ range i, cat := catHierarchy }}
:
{{ if i == last }}
{{ cat.Name }}
{{ else }}
<a href="/find?mode=COM&catid={{ cat.CatId }}"
class="text-blue-700 hover:text-blue-900 font-bold">{{ cat.Name }}</a>
{{ end }}
{{ end }}
</h2>
<div class="bg-gray-50 p-6 rounded-lg">
<h3 class="text-base font-bold text-black mb-4">Subcategories:</h3>
<div class="grid grid-cols-1 md:grid-cols-1 gap-1">
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=1"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Arts</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=2"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Business</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=3"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Computers</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=4"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Games</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=5"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Health</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=6"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Home</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=7"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">News</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=8"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Recreation</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=9"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Reference and Education</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=10"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Regional</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=11"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Science</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=12"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Shopping</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=13"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Society</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=14"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Sports</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=15"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">System</a>
</div>
<div class="flex items-start gap-1">
<span class="text-lg pt-0.5">🟣</span>
<a href="http://necrovenice:8080/venice/find.js.vs?disp=0&cat=0"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">Unclassified</a>
{{ if len(catSubs) > 0 }}
<div class="bg-gray-50 p-6 rounded-lg">
<h3 class="text-base font-bold text-black mb-4">Subcategories:</h3>
<div class="grid grid-cols-1 md:grid-cols-1 gap-1">
{{ range _, cat := catSubs }}
{{ if !cat.HideDirectory || showHiddenCat }}
<div class="flex items-start gap-1">
<span class="text-sm pt-0.5">🟣</span>
<a href="/find?mode=COM&catid={{ cat.CatId }}"
class="text-blue-700 hover:text-blue-900 font-bold text-sm">{{ cat.Name }}</a>
{{ if cat.SymLink != -1 }}<span class="text-sm pt-0.5">🔗</span>{{ end }}
</div>
{{ end }}
{{ end }}
</div>
</div>
</div>
{{ end }}
</div>
{{ end }}
</div>