From 56a6190ce9e032ba02eef4876c87ee2b0f5452bc Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Mon, 26 Aug 2024 20:47:14 -0700 Subject: [PATCH] User Forums: Sort options and pagination * The Explore tab can now sort forums by their: * Most recently updated thread * Topics, Posts or Users (counts) * Show owner information in forum cards * Passive pagination support for the "My List" on forum home page. * Only visible when there are >20 favorited Forums. --- pkg/config/page_sizes.go | 1 + pkg/controller/forum/browse.go | 7 +++++ pkg/controller/forum/forums.go | 13 ++++++--- pkg/models/forum.go | 38 ++++++++++++++++++++++++++ web/templates/forum/index.html | 49 ++++++++++++++++++++++++++++++---- 5 files changed, 99 insertions(+), 9 deletions(-) diff --git a/pkg/config/page_sizes.go b/pkg/config/page_sizes.go index 19feadb..4c7103e 100644 --- a/pkg/config/page_sizes.go +++ b/pkg/config/page_sizes.go @@ -24,6 +24,7 @@ var ( PageSizeInboxThread = 10 // conversation view PageSizeBrowseForums = 20 PageSizeForums = 100 // TODO: for main category index view + PageSizeMyListForums = 20 // "My List" pager on forum home (categories) page. PageSizeThreadList = 20 // 20 threads per board, 20 posts per thread PageSizeForumAdmin = 20 PageSizeDashboardNotifications = 50 diff --git a/pkg/controller/forum/browse.go b/pkg/controller/forum/browse.go index cf4ae55..24379e9 100644 --- a/pkg/controller/forum/browse.go +++ b/pkg/controller/forum/browse.go @@ -20,6 +20,13 @@ func Explore() http.HandlerFunc { "created_at asc", "title asc", "title desc", + + // Special sort handlers. + // See PaginateForums for expanded handlers for these. + "by_latest", + "by_threads", + "by_posts", + "by_users", } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/controller/forum/forums.go b/pkg/controller/forum/forums.go index eb69e08..59fcdc8 100644 --- a/pkg/controller/forum/forums.go +++ b/pkg/controller/forum/forums.go @@ -33,14 +33,13 @@ func Landing() http.HandlerFunc { // Get all the categorized index forums. // XXX: we get a large page size to get ALL official forums - var pager = &models.Pagination{ + // This pager is hardcoded and doesn't parse from ?page= params. + var indexPager = &models.Pagination{ Page: 1, PerPage: config.PageSizeForums, Sort: "title asc", } - pager.ParsePage(r) - - forums, err := models.PaginateForums(currentUser, config.ForumCategories, nil, false, pager) + forums, err := models.PaginateForums(currentUser, config.ForumCategories, nil, false, indexPager) if err != nil { session.FlashError(w, r, "Couldn't paginate forums: %s", err) templates.Redirect(w, "/") @@ -51,6 +50,12 @@ func Landing() http.HandlerFunc { categorized := models.CategorizeForums(forums, config.ForumCategories) // Inject the "My List" Category if the user subscribes to forums. + var pager = &models.Pagination{ + Page: 1, + PerPage: config.PageSizeMyListForums, + Sort: "by_latest", + } + pager.ParsePage(r) if config.UserForumsEnabled { myList, err := models.PaginateForums(currentUser, nil, nil, true, pager) if err != nil { diff --git a/pkg/models/forum.go b/pkg/models/forum.go index a58366d..cb971b0 100644 --- a/pkg/models/forum.go +++ b/pkg/models/forum.go @@ -85,6 +85,13 @@ Parameters: - userID: of who is looking - categories: optional, filter within categories - pager + +The pager Sort accepts a couple of custom values for more advanced sorting: + +- by_latest: recently updated posts +- by_threads: thread count +- by_posts: post count +- by_users: user count */ func PaginateForums(user *User, categories []string, search *Search, subscribed bool, pager *Pagination) ([]*Forum, error) { var ( @@ -159,6 +166,37 @@ func PaginateForums(user *User, categories []string, search *Search, subscribed ) } + // Custom SORT parameters. + switch pager.Sort { + case "by_latest": + pager.Sort = `( + SELECT MAX(threads.updated_at) + FROM threads + WHERE threads.forum_id = forums.id + ) DESC NULLS LAST` + case "by_threads": + pager.Sort = `( + SELECT count(threads.id) + FROM threads + WHERE threads.forum_id = forums.id + ) DESC` + case "by_posts": + pager.Sort = `( + SELECT count(comments.id) + FROM threads + JOIN comments ON comments.table_name='threads' AND comments.table_id=threads.id + WHERE threads.forum_id = forums.id + ) DESC` + case "by_users": + pager.Sort = `( + SELECT count(distinct(users.id)) + FROM threads + JOIN comments ON comments.table_name='threads' AND comments.table_id=threads.id + JOIN users ON comments.user_id=users.id + WHERE threads.forum_id = forums.id + ) DESC` + } + query = query.Order(pager.Sort) query.Model(&Forum{}).Count(&pager.Total) result := query.Offset(pager.GetOffset()).Limit(pager.PerPage).Find(&fs) diff --git a/web/templates/forum/index.html b/web/templates/forum/index.html index 0589325..0bae223 100644 --- a/web/templates/forum/index.html +++ b/web/templates/forum/index.html @@ -87,9 +87,17 @@
@@ -121,16 +129,22 @@ {{end}} {{range .Categories}} + {{$IsMyList := eq .Category "My List"}}
{{if .Category}}

{{.Category}} - {{if eq .Category "My List"}} + {{if $IsMyList}} {{end}}

{{end}} + + {{if and $IsMyList (gt $Root.Pager.Pages 1)}} + {{SimplePager $Root.Pager}} + {{end}} + {{if eq (len .Forums) 0}} There are no forums under this category. @@ -159,7 +173,7 @@ {{end}}
-
+
{{if .Explicit}} @@ -189,6 +203,25 @@ {{end}}
+ + {{if .Category}} + + {{else}} +
+ by + {{template "avatar-16x16" .Owner}} + {{if .Owner.Username}} + + {{or .Owner.Username "[unavailable]"}} + + {{else}} + [unavailable] + {{end}} +
+ {{end}} +
@@ -251,6 +284,12 @@
{{end}} {{end}} + + + {{if and $IsMyList (gt $Root.Pager.Pages 1)}} + {{SimplePager $Root.Pager}} +
+ {{end}}
{{end}}