diff --git a/database/community.go b/database/community.go index 950a49f..e9f8ad9 100644 --- a/database/community.go +++ b/database/community.go @@ -10,6 +10,7 @@ package database import ( + "database/sql" "errors" "fmt" "slices" @@ -139,6 +140,18 @@ func (c *Community) Host() (*User, error) { return AmGetUser(*c.HostUid) } +// HostQ returns the reference to the community's host, quietly. +func (c *Community) HostQ() *User { + if c.HostUid == nil { + return nil + } + u, err := AmGetUser(*c.HostUid) + if err != nil { + return nil + } + return u +} + func (c *Community) LanguageTag() (*language.Tag, error) { if c.Language == nil { return nil, nil @@ -196,6 +209,26 @@ func (c *Community) Membership(u *User) (bool, bool, uint16, error) { return false, false, uint16(0), err } +// MemberCountQ returns the number of members in the community, quietly. +func (c *Community) MemberCountQ(hidden bool) int { + var rs *sql.Rows + var err error + if hidden { + rs, err = amdb.Query("SELECT COUNT(*) FROM commmember WHERE commid = ?", c.Id) + } else { + rs, err = amdb.Query("SELECT COUNT(*) FROM commmember WHERE commid = ? AND hidden = 0", c.Id) + } + if err != nil { + return -1 + } + if rs.Next() { + var rc int + rs.Scan(&rc) + return rc + } + return -1 +} + /* TestPermission is shorthand that tests if a user has a permission with respect to the community. * Parameters: * user - The user to be checked. @@ -620,3 +653,67 @@ func AmCreateCommunity(name string, alias string, hostUid int32, language *strin fmt.Sprintf("name=%s", comm.Name), fmt.Sprintf("alias=%s", comm.Alias)) return comm, nil } + +/* AmGetCommunitiesForCategory returns a list of communities for the specified category. + * Parameters: + * catid - Category ID to search for. + * offset - Number of communities to skip at beginning of list. + * max - Maximum number of communities to return. + * showAll - Include communities that are "hidden in directory." + * Returns: + * Array of Community pointers representing the return elements. + * The total number of communities matching this query (could be greater than max) + * Standard Go error status. + */ +func AmGetCommunitiesForCategory(catid int32, offset int, max int, showAll bool) ([]*Community, int, error) { + var rs *sql.Rows + var err error + if showAll { + rs, err = amdb.Query("SELECT COUNT(*) FROM communities WHERE catid = ?", catid) + } else { + rs, err = amdb.Query("SELECT COUNT(*) FROM communities WHERE catid = ? AND hide_dir = 0", catid) + } + if err != nil { + return nil, -1, err + } + if !rs.Next() { + return nil, -1, errors.New("internal error getting total match count") + } + var total int + rs.Scan(&total) + if total == 0 { + return make([]*Community, 0), 0, nil // short-circuit return + } + if showAll { + if offset > 0 { + rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? ORDER BY commname LIMIT ? OFFSET ?", + catid, max, offset) + } else { + rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? ORDER BY commname LIMIT ?", catid, max) + } + } else { + if offset > 0 { + rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? AND hide_dir = 0 ORDER BY commname LIMIT ? OFFSET ?", + catid, max, offset) + } else { + rs, err = amdb.Query("SELECT commid FROM communities WHERE catid = ? AND hide_dir = 0 ORDER BY commname LIMIT ?", catid, max) + } + } + if err != nil { + return nil, total, err + } + rcCap := max + if rcCap > 10000 { + rcCap = 10000 + } + rc := make([]*Community, 0, rcCap) + for rs.Next() { + var commid int32 + rs.Scan(&commid) + c, err := AmGetCommunity(commid) + if err == nil { + rc = append(rc, c) + } + } + return rc, total, nil +} diff --git a/find.go b/find.go index b7ce0a9..c058d4a 100644 --- a/find.go +++ b/find.go @@ -10,6 +10,7 @@ package main import ( + "fmt" "strconv" "git.erbosoft.com/amy/amsterdam/database" @@ -17,7 +18,7 @@ import ( ) // loadCategoryInformation loads the current category information to the context. -func loadCategoryInformation(ctxt ui.AmContext) error { +func loadCategoryInformation(ctxt ui.AmContext, offset int) error { u := ctxt.CurrentUser() catid := int32(-1) p := ctxt.Parameter("catid") @@ -42,7 +43,8 @@ func loadCategoryInformation(ctxt ui.AmContext) error { } ctxt.SetSession("find.catid", catid) ctxt.VarMap().Set("catid", catid) - ctxt.VarMap().Set("showHiddenCat", database.AmTestPermission("Global.ShowHiddenCategories", u.BaseLevel)) + showHidden := database.AmTestPermission("Global.ShowHiddenCategories", u.BaseLevel) + ctxt.VarMap().Set("showHiddenCat", showHidden) hier, err := database.AmGetCategoryHierarchy(catid) if err != nil { return err @@ -53,7 +55,29 @@ func loadCategoryInformation(ctxt ui.AmContext) error { return err } ctxt.VarMap().Set("catSubs", subs) - // TODO: set matching communities as well + ctxt.VarMap().Set("displayCats", true) + + if catid > -1 { + // search for communities in this category + listMax := int(ctxt.Globals().MaxSearchPage) + commList, numComm, err := database.AmGetCommunitiesForCategory(catid, offset*listMax, listMax, showHidden) + if err != nil { + return err + } + if len(commList) == 0 { + ctxt.VarMap().Set("resultHeader", "Communities in Category (None)") + } else { + ctxt.VarMap().Set("resultHeader", fmt.Sprintf("Communities in Category (Displaying %d-%d of %d)", + offset*listMax+1, offset*listMax+len(commList), numComm)) + ctxt.VarMap().Set("resultList", commList) + if offset > 0 { + ctxt.VarMap().Set("resultShowPrev", true) + } + if offset*listMax+len(commList) < numComm { + ctxt.VarMap().Set("resultShowNext", true) + } + } + } return nil } @@ -79,6 +103,14 @@ func FindPage(ctxt ui.AmContext) (string, any, error) { if mode == "" { mode = "COM" } + ofs := 0 + p = ctxt.Parameter("ofs") + if p != "" { + v, err := strconv.Atoi(p) + if err == nil { + ofs = v + } + } ctxt.SetSession("find.mode", mode) ctxt.VarMap().Set("mode", mode) switch mode { @@ -86,7 +118,7 @@ func FindPage(ctxt ui.AmContext) (string, any, error) { ctxt.VarMap().Set("field", "name") ctxt.VarMap().Set("oper", "st") ctxt.VarMap().Set("term", "") - err := loadCategoryInformation(ctxt) + err := loadCategoryInformation(ctxt, ofs) if err != nil { return ui.ErrorPage(ctxt, err) } diff --git a/ui/views/comprofile.jet b/ui/views/comprofile.jet index 6aef5c9..6eda762 100644 --- a/ui/views/comprofile.jet +++ b/ui/views/comprofile.jet @@ -64,7 +64,7 @@ Category: {{ range i := categories }} {{ if i > 0 }}: {{ end }} - {{ .Name }} {{ end }} diff --git a/ui/views/find.jet b/ui/views/find.jet index 5be49e3..f23c216 100644 --- a/ui/views/find.jet +++ b/ui/views/find.jet @@ -139,7 +139,7 @@ - {{ if mode == "COM" }} + {{ if isset(displayCats) }}

@@ -181,4 +181,57 @@ {{ end }}
{{ end }} + + {{ if isset(resultHeader) }} + +
+
+
{{ resultHeader }}
+
+ {{ if isset(resultList) }} + +
+
+ {{ range _, rx := resultList }} + {{ if mode == "COM" }} + +
+ 🟣 +
+ +
+
+ Host: + {{ h := rx.HostQ() }} + {{ h.Username }} + - + {{ n := rx.MemberCountQ(false) }} + {{ if n == 1 }} + 1 member + {{ else }} + {{ n }} members + {{ end }} +
+
+ Latest activity: [Today, 9:52:48 PM] +
+
{{ rx.Synopsis }}
+
+
+
+ {{ else if mode == "USR" }} + TODO: I don't know USR yet + {{ else if mode == "CAT" }} + TODO: I don't know CAT yet + {{ else if mode == "PST" }} + TODO: I don't know PST yet + {{ end }} + {{ end }} +
+
+ {{ end }} + {{ end }}