landed community results when browsing categories - missing pagination buttons, community activity, proper member counts
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -139,6 +140,18 @@ func (c *Community) Host() (*User, error) {
|
|||||||
return AmGetUser(*c.HostUid)
|
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) {
|
func (c *Community) LanguageTag() (*language.Tag, error) {
|
||||||
if c.Language == nil {
|
if c.Language == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -196,6 +209,26 @@ func (c *Community) Membership(u *User) (bool, bool, uint16, error) {
|
|||||||
return false, false, uint16(0), err
|
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.
|
/* TestPermission is shorthand that tests if a user has a permission with respect to the community.
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* user - The user to be checked.
|
* 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))
|
fmt.Sprintf("name=%s", comm.Name), fmt.Sprintf("alias=%s", comm.Alias))
|
||||||
return comm, nil
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"git.erbosoft.com/amy/amsterdam/database"
|
"git.erbosoft.com/amy/amsterdam/database"
|
||||||
@@ -17,7 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// loadCategoryInformation loads the current category information to the context.
|
// 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()
|
u := ctxt.CurrentUser()
|
||||||
catid := int32(-1)
|
catid := int32(-1)
|
||||||
p := ctxt.Parameter("catid")
|
p := ctxt.Parameter("catid")
|
||||||
@@ -42,7 +43,8 @@ func loadCategoryInformation(ctxt ui.AmContext) error {
|
|||||||
}
|
}
|
||||||
ctxt.SetSession("find.catid", catid)
|
ctxt.SetSession("find.catid", catid)
|
||||||
ctxt.VarMap().Set("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)
|
hier, err := database.AmGetCategoryHierarchy(catid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -53,7 +55,29 @@ func loadCategoryInformation(ctxt ui.AmContext) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ctxt.VarMap().Set("catSubs", subs)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +103,14 @@ func FindPage(ctxt ui.AmContext) (string, any, error) {
|
|||||||
if mode == "" {
|
if mode == "" {
|
||||||
mode = "COM"
|
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.SetSession("find.mode", mode)
|
||||||
ctxt.VarMap().Set("mode", mode)
|
ctxt.VarMap().Set("mode", mode)
|
||||||
switch mode {
|
switch mode {
|
||||||
@@ -86,7 +118,7 @@ func FindPage(ctxt ui.AmContext) (string, any, error) {
|
|||||||
ctxt.VarMap().Set("field", "name")
|
ctxt.VarMap().Set("field", "name")
|
||||||
ctxt.VarMap().Set("oper", "st")
|
ctxt.VarMap().Set("oper", "st")
|
||||||
ctxt.VarMap().Set("term", "")
|
ctxt.VarMap().Set("term", "")
|
||||||
err := loadCategoryInformation(ctxt)
|
err := loadCategoryInformation(ctxt, ofs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ui.ErrorPage(ctxt, err)
|
return ui.ErrorPage(ctxt, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<strong>Category:</strong>
|
<strong>Category:</strong>
|
||||||
{{ range i := categories }}
|
{{ range i := categories }}
|
||||||
{{ if i > 0 }}: {{ end }}
|
{{ if i > 0 }}: {{ end }}
|
||||||
<a href="/TODO/find/communities-for-category"
|
<a href="/find?mode=COM&catid={{ .CatId }}"
|
||||||
class="text-blue-700 hover:text-blue-900">{{ .Name }}</a>
|
class="text-blue-700 hover:text-blue-900">{{ .Name }}</a>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+54
-1
@@ -139,7 +139,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Category Listing -->
|
<!-- Category Listing -->
|
||||||
{{ if mode == "COM" }}
|
{{ if isset(displayCats) }}
|
||||||
<div class="max-w-3xl">
|
<div class="max-w-3xl">
|
||||||
<hr class="border-gray-400 mb-4">
|
<hr class="border-gray-400 mb-4">
|
||||||
|
|
||||||
@@ -181,4 +181,57 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if isset(resultHeader) }}
|
||||||
|
<!-- Search results -->
|
||||||
|
<hr class="border-gray-400 mb-4">
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<div class="text-sm text-black font-bold">{{ resultHeader }}</div>
|
||||||
|
</div>
|
||||||
|
{{ if isset(resultList) }}
|
||||||
|
<!-- Results List -->
|
||||||
|
<div class="bg-gray-50 p-6 rounded-lg">
|
||||||
|
<div class="space-y-4">
|
||||||
|
{{ range _, rx := resultList }}
|
||||||
|
{{ if mode == "COM" }}
|
||||||
|
<!-- Community Result -->
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<span class="text-sm pt-0.5 flex-shrink-0">🟣</span>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="mb-2">
|
||||||
|
<a href="/comm/{{ rx.Alias }}/profile"
|
||||||
|
class="text-blue-700 hover:text-blue-900 font-bold text-base">{{ rx.Name }}</a>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-gray-700 space-y-1">
|
||||||
|
<div>
|
||||||
|
<span class="font-medium">Host:</span>
|
||||||
|
{{ h := rx.HostQ() }}
|
||||||
|
<a href="/user/{{ h.Username }}" class="text-blue-700 hover:text-blue-900">{{ h.Username }}</a>
|
||||||
|
<span class="mx-2">-</span>
|
||||||
|
{{ n := rx.MemberCountQ(false) }}
|
||||||
|
{{ if n == 1 }}
|
||||||
|
<span>1 member</span>
|
||||||
|
{{ else }}
|
||||||
|
<span>{{ n }} members</span>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="font-medium">Latest activity:</span> [Today, 9:52:48 PM]
|
||||||
|
</div>
|
||||||
|
<div class="italic text-gray-600 mt-2">{{ rx.Synopsis }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ 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 }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user