Skip to content

Only use prev and next buttons for pagination on user dashboard #33981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 39 additions & 22 deletions modules/paginator/paginator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package paginator

import "code.gitea.io/gitea/modules/util"

/*
In template:

Expand Down Expand Up @@ -32,25 +34,43 @@ Output:

// Paginator represents a set of results of pagination calculations.
type Paginator struct {
total int // total rows count
total int // total rows count, -1 means unknown
totalPages int // total pages count, -1 means unknown
current int // current page number
curRows int // current page rows count

pagingNum int // how many rows in one page
current int // current page number
numPages int // how many pages to show on the UI
}

// New initialize a new pagination calculation and returns a Paginator as result.
func New(total, pagingNum, current, numPages int) *Paginator {
if pagingNum <= 0 {
pagingNum = 1
pagingNum = max(pagingNum, 1)
totalPages := util.Iif(total == -1, -1, (total+pagingNum-1)/pagingNum)
if total >= 0 {
current = min(current, totalPages)
}
if current <= 0 {
current = 1
current = max(current, 1)
return &Paginator{
total: total,
totalPages: totalPages,
current: current,
pagingNum: pagingNum,
numPages: numPages,
}
p := &Paginator{total, pagingNum, current, numPages}
if p.current > p.TotalPages() {
p.current = p.TotalPages()
}

func (p *Paginator) SetCurRows(rows int) {
// For "unlimited paging", we need to know the rows of current page to determine if there is a next page.
// There is still an edge case: when curRows==pagingNum, then the "next page" will be an empty page.
// Ideally we should query one more row to determine if there is really a next page, but it's impossible in current framework.
p.curRows = rows
if p.total == -1 && p.current == 1 && !p.HasNext() {
// if there is only one page for the "unlimited paging", set total rows/pages count
// then the tmpl could decide to hide the nav bar.
p.total = rows
p.totalPages = util.Iif(p.total == 0, 0, 1)
}
return p
}

// IsFirst returns true if current page is the first page.
Expand All @@ -72,7 +92,10 @@ func (p *Paginator) Previous() int {

// HasNext returns true if there is a next page relative to current page.
func (p *Paginator) HasNext() bool {
return p.total > p.current*p.pagingNum
if p.total == -1 {
return p.curRows >= p.pagingNum
}
return p.current*p.pagingNum < p.total
}

func (p *Paginator) Next() int {
Expand All @@ -84,10 +107,7 @@ func (p *Paginator) Next() int {

// IsLast returns true if current page is the last page.
func (p *Paginator) IsLast() bool {
if p.total == 0 {
return true
}
return p.total > (p.current-1)*p.pagingNum && !p.HasNext()
return !p.HasNext()
}

// Total returns number of total rows.
Expand All @@ -97,10 +117,7 @@ func (p *Paginator) Total() int {

// TotalPages returns number of total pages.
func (p *Paginator) TotalPages() int {
if p.total == 0 {
return 1
}
return (p.total + p.pagingNum - 1) / p.pagingNum
return p.totalPages
}

// Current returns current page number.
Expand Down Expand Up @@ -135,10 +152,10 @@ func getMiddleIdx(numPages int) int {
// If value is -1 means "..." that more pages are not showing.
func (p *Paginator) Pages() []*Page {
if p.numPages == 0 {
return []*Page{}
} else if p.numPages == 1 && p.TotalPages() == 1 {
return nil
} else if p.total == -1 || (p.numPages == 1 && p.TotalPages() == 1) {
// Only show current page.
return []*Page{{1, true}}
return []*Page{{p.current, true}}
}

// Total page number is less or equal.
Expand Down
4 changes: 1 addition & 3 deletions modules/paginator/paginator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ func TestPaginator(t *testing.T) {
t.Run("Only current page", func(t *testing.T) {
p := New(0, 10, 1, 1)
pages := p.Pages()
assert.Len(t, pages, 1)
assert.Equal(t, 1, pages[0].Num())
assert.True(t, pages[0].IsCurrent())
assert.Empty(t, pages) // no "total", so no pages

p = New(1, 10, 1, 1)
pages = p.Pages()
Expand Down
5 changes: 2 additions & 3 deletions routers/web/user/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,10 @@ func Dashboard(ctx *context.Context) {
return
}

ctx.Data["Feeds"] = feeds

pager := context.NewPagination(int(count), setting.UI.FeedPagingNum, page, 5)
pager := context.NewPagination(count, setting.UI.FeedPagingNum, page, 5).WithCurRows(len(feeds))
pager.AddParamFromRequest(ctx.Req)
ctx.Data["Page"] = pager
ctx.Data["Feeds"] = feeds

ctx.HTML(http.StatusOK, tplDashboard)
}
Expand Down
6 changes: 6 additions & 0 deletions services/context/pagination.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ type Pagination struct {

// NewPagination creates a new instance of the Pagination struct.
// "pagingNum" is "page size" or "limit", "current" is "page"
// total=-1 means only showing prev/next
func NewPagination(total, pagingNum, current, numPages int) *Pagination {
p := &Pagination{}
p.Paginater = paginator.New(total, pagingNum, current, numPages)
return p
}

func (p *Pagination) WithCurRows(n int) *Pagination {
p.Paginater.SetCurRows(n)
return p
}

func (p *Pagination) AddParamFromRequest(req *http.Request) {
for key, values := range req.URL.Query() {
if key == "page" || len(values) == 0 || (len(values) == 1 && values[0] == "") {
Expand Down
13 changes: 3 additions & 10 deletions services/feed/feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,17 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)

func userFeedCacheKey(userID int64) string {
return fmt.Sprintf("user_feed_%d", userID)
}

func GetFeedsForDashboard(ctx context.Context, opts activities_model.GetFeedsOptions) (activities_model.ActionList, int64, error) {
func GetFeedsForDashboard(ctx context.Context, opts activities_model.GetFeedsOptions) (activities_model.ActionList, int, error) {
opts.DontCount = opts.RequestedTeam == nil && opts.Date == ""
results, cnt, err := activities_model.GetFeeds(ctx, opts)
if err != nil {
return nil, 0, err
}
if opts.DontCount {
cnt, err = cache.GetInt64(userFeedCacheKey(opts.Actor.ID), func() (int64, error) {
return activities_model.CountUserFeeds(ctx, opts.Actor.ID)
})
}
return results, cnt, err
return results, util.Iif(opts.DontCount, -1, int(cnt)), err
}

// GetFeeds returns actions according to the provided options
Expand Down
16 changes: 13 additions & 3 deletions templates/base/paginate.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,42 @@
{{$paginationLink := $.Link}}
{{if eq $paginationLink AppSubUrl}}{{$paginationLink = print $paginationLink "/"}}{{end}}
{{with .Page.Paginater}}
{{if gt .TotalPages 1}}
{{if or (eq .TotalPages -1) (gt .TotalPages 1)}}
{{$showFirstLast := gt .TotalPages 1}}
<div class="center page buttons">
<div class="ui borderless pagination menu">
{{if $showFirstLast}}
<a class="{{if .IsFirst}}disabled{{end}} item navigation" {{if not .IsFirst}}href="{{$paginationLink}}{{if $paginationParams}}?{{$paginationParams}}{{end}}"{{end}}>
{{svg "gitea-double-chevron-left" 16 "tw-mr-1"}}
<span class="navigation_label">{{ctx.Locale.Tr "admin.first_page"}}</span>
</a>
{{end}}

<a class="{{if not .HasPrevious}}disabled{{end}} item navigation" {{if .HasPrevious}}href="{{$paginationLink}}?page={{.Previous}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>
{{svg "octicon-chevron-left" 16 "tw-mr-1"}}
<span class="navigation_label">{{ctx.Locale.Tr "repo.issues.previous"}}</span>
</a>
{{range .Pages}}
{{$pages := .Pages}}
{{$pagesLen := len $pages}}
{{range $pages}}
{{if eq .Num -1}}
<a class="disabled item">...</a>
{{else}}
<a class="{{if .IsCurrent}}active {{end}}item" {{if not .IsCurrent}}href="{{$paginationLink}}?page={{.Num}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>{{.Num}}</a>
{{/* do not highlight the current page if there is only one page */}}
<a class="{{if and .IsCurrent (gt $pagesLen 1)}}active {{end}}item" {{if not .IsCurrent}}href="{{$paginationLink}}?page={{.Num}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>{{.Num}}</a>
{{end}}
{{end}}
<a class="{{if not .HasNext}}disabled{{end}} item navigation" {{if .HasNext}}href="{{$paginationLink}}?page={{.Next}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>
<span class="navigation_label">{{ctx.Locale.Tr "repo.issues.next"}}</span>
{{svg "octicon-chevron-right" 16 "tw-ml-1"}}
</a>

{{if $showFirstLast}}
<a class="{{if .IsLast}}disabled{{end}} item navigation" {{if not .IsLast}}href="{{$paginationLink}}?page={{.TotalPages}}{{if $paginationParams}}&{{$paginationParams}}{{end}}"{{end}}>
<span class="navigation_label">{{ctx.Locale.Tr "admin.last_page"}}</span>
{{svg "gitea-double-chevron-right" 16 "tw-ml-1"}}
</a>
{{end}}
</div>
</div>
{{end}}
Expand Down
2 changes: 1 addition & 1 deletion templates/user/dashboard/dashboard.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<div class="flex-container-main">
{{template "base/alert" .}}
{{template "user/heatmap" .}}
{{if .Feeds}}
{{if .Page.Paginater.TotalPages}}
{{template "user/dashboard/feeds" .}}
{{else}}
{{template "user/dashboard/guide" .}}
Expand Down