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.
This commit is contained in:
parent
3921691319
commit
56a6190ce9
|
@ -24,6 +24,7 @@ var (
|
||||||
PageSizeInboxThread = 10 // conversation view
|
PageSizeInboxThread = 10 // conversation view
|
||||||
PageSizeBrowseForums = 20
|
PageSizeBrowseForums = 20
|
||||||
PageSizeForums = 100 // TODO: for main category index view
|
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
|
PageSizeThreadList = 20 // 20 threads per board, 20 posts per thread
|
||||||
PageSizeForumAdmin = 20
|
PageSizeForumAdmin = 20
|
||||||
PageSizeDashboardNotifications = 50
|
PageSizeDashboardNotifications = 50
|
||||||
|
|
|
@ -20,6 +20,13 @@ func Explore() http.HandlerFunc {
|
||||||
"created_at asc",
|
"created_at asc",
|
||||||
"title asc",
|
"title asc",
|
||||||
"title desc",
|
"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) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -33,14 +33,13 @@ func Landing() http.HandlerFunc {
|
||||||
|
|
||||||
// Get all the categorized index forums.
|
// Get all the categorized index forums.
|
||||||
// XXX: we get a large page size to get ALL official 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,
|
Page: 1,
|
||||||
PerPage: config.PageSizeForums,
|
PerPage: config.PageSizeForums,
|
||||||
Sort: "title asc",
|
Sort: "title asc",
|
||||||
}
|
}
|
||||||
pager.ParsePage(r)
|
forums, err := models.PaginateForums(currentUser, config.ForumCategories, nil, false, indexPager)
|
||||||
|
|
||||||
forums, err := models.PaginateForums(currentUser, config.ForumCategories, nil, false, pager)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.FlashError(w, r, "Couldn't paginate forums: %s", err)
|
session.FlashError(w, r, "Couldn't paginate forums: %s", err)
|
||||||
templates.Redirect(w, "/")
|
templates.Redirect(w, "/")
|
||||||
|
@ -51,6 +50,12 @@ func Landing() http.HandlerFunc {
|
||||||
categorized := models.CategorizeForums(forums, config.ForumCategories)
|
categorized := models.CategorizeForums(forums, config.ForumCategories)
|
||||||
|
|
||||||
// Inject the "My List" Category if the user subscribes to forums.
|
// 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 {
|
if config.UserForumsEnabled {
|
||||||
myList, err := models.PaginateForums(currentUser, nil, nil, true, pager)
|
myList, err := models.PaginateForums(currentUser, nil, nil, true, pager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -85,6 +85,13 @@ Parameters:
|
||||||
- userID: of who is looking
|
- userID: of who is looking
|
||||||
- categories: optional, filter within categories
|
- categories: optional, filter within categories
|
||||||
- pager
|
- 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) {
|
func PaginateForums(user *User, categories []string, search *Search, subscribed bool, pager *Pagination) ([]*Forum, error) {
|
||||||
var (
|
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 = query.Order(pager.Sort)
|
||||||
query.Model(&Forum{}).Count(&pager.Total)
|
query.Model(&Forum{}).Count(&pager.Total)
|
||||||
result := query.Offset(pager.GetOffset()).Limit(pager.PerPage).Find(&fs)
|
result := query.Offset(pager.GetOffset()).Limit(pager.PerPage).Find(&fs)
|
||||||
|
|
|
@ -87,9 +87,17 @@
|
||||||
<label class="label" for="sort">Sort by:</label>
|
<label class="label" for="sort">Sort by:</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
<select id="sort" name="sort">
|
<select id="sort" name="sort">
|
||||||
<option value="title asc"{{if eq .Sort "title asc"}} selected{{end}}>Title (A-Z)</option>
|
<optgroup label="Forum">
|
||||||
<option value="title desc"{{if eq .Sort "title desc"}} selected{{end}}>Title (Z-A)</option>
|
<option value="title asc"{{if eq .Sort "title asc"}} selected{{end}}>Title (A-Z)</option>
|
||||||
<option value="created_at desc"{{if eq .Sort "created_at desc"}} selected{{end}}>Recently created</option>
|
<option value="title desc"{{if eq .Sort "title desc"}} selected{{end}}>Title (Z-A)</option>
|
||||||
|
<option value="created_at desc"{{if eq .Sort "created_at desc"}} selected{{end}}>Recently created</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Contents">
|
||||||
|
<option value="by_latest"{{if eq .Sort "by_latest"}} selected{{end}}>Latest post</option>
|
||||||
|
<option value="by_threads"{{if eq .Sort "by_threads"}} selected{{end}}>Topic count</option>
|
||||||
|
<option value="by_posts"{{if eq .Sort "by_posts"}} selected{{end}}>Post count</option>
|
||||||
|
<option value="by_users"{{if eq .Sort "by_users"}} selected{{end}}>User count</option>
|
||||||
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -121,16 +129,22 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range .Categories}}
|
{{range .Categories}}
|
||||||
|
{{$IsMyList := eq .Category "My List"}}
|
||||||
<div class="block p-4">
|
<div class="block p-4">
|
||||||
{{if .Category}}
|
{{if .Category}}
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
{{.Category}}
|
{{.Category}}
|
||||||
{{if eq .Category "My List"}}
|
{{if $IsMyList}}
|
||||||
<i class="fa fa-book-bookmark ml-2"></i>
|
<i class="fa fa-book-bookmark ml-2"></i>
|
||||||
{{end}}
|
{{end}}
|
||||||
</h1>
|
</h1>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
<!-- My List: show pagers if needed -->
|
||||||
|
{{if and $IsMyList (gt $Root.Pager.Pages 1)}}
|
||||||
|
{{SimplePager $Root.Pager}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{if eq (len .Forums) 0}}
|
{{if eq (len .Forums) 0}}
|
||||||
<em>
|
<em>
|
||||||
There are no forums under this category.
|
There are no forums under this category.
|
||||||
|
@ -159,7 +173,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="mb-3">
|
||||||
{{if .Explicit}}
|
{{if .Explicit}}
|
||||||
<span class="tag is-danger is-light">
|
<span class="tag is-danger is-light">
|
||||||
<span class="icon"><i class="fa fa-fire"></i></span>
|
<span class="icon"><i class="fa fa-fire"></i></span>
|
||||||
|
@ -189,6 +203,25 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Owner line -->
|
||||||
|
{{if .Category}}
|
||||||
|
<div class="mt-2 has-text-grey" style="font-size: smaller">
|
||||||
|
by <a href="/f/{{.Fragment}}">{{PrettyTitle}}</a>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="mt-2 has-text-grey" style="font-size: smaller">
|
||||||
|
by
|
||||||
|
{{template "avatar-16x16" .Owner}}
|
||||||
|
{{if .Owner.Username}}
|
||||||
|
<a href="/u/{{.Owner.Username}}" class="has-text-grey">
|
||||||
|
<strong>{{or .Owner.Username "[unavailable]"}}</strong>
|
||||||
|
</a>
|
||||||
|
{{else}}
|
||||||
|
[unavailable]
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column py-1">
|
<div class="column py-1">
|
||||||
<div class="box has-background-success-light has-text-dark">
|
<div class="box has-background-success-light has-text-dark">
|
||||||
|
@ -251,6 +284,12 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
<!-- My List: show pagers -->
|
||||||
|
{{if and $IsMyList (gt $Root.Pager.Pages 1)}}
|
||||||
|
{{SimplePager $Root.Pager}}
|
||||||
|
<hr class="mb-0">
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}<!-- range .Categories -->
|
{{end}}<!-- range .Categories -->
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user