-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpaginator.go
115 lines (98 loc) · 2.25 KB
/
paginator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package paginator
import (
"errors"
"math"
"gorm.io/gorm"
)
type Pagination struct {
TotalRecords int64 `json:"totalRecords"`
TotalPage int `json:"totalPage"`
Offset int `json:"offset"`
Limit int `json:"limit"`
Page int `json:"page"`
PrevPage int `json:"prevPage"`
NextPage int `json:"nextPage"`
}
type Paging struct {
Page int `json:"page"`
OrderBy []string `json:"orderBy"`
Limit int `json:"limit"`
ShowSQL bool
}
type Param struct {
DB *gorm.DB
Paging *Paging
}
// Endpoint for pagination
func Pages(p *Param, result interface{}) (paginator *Pagination, err error) {
var (
done = make(chan bool, 1)
db = p.DB.Session(&gorm.Session{})
defPage = 1
defLimit = 20
count int64
offset int
)
// get all counts
go getCounts(db, result, done, &count)
// if not defined
if p.Paging == nil {
p.Paging = &Paging{}
}
// debug sql
if p.Paging.ShowSQL {
db = db.Debug()
}
// limit
if p.Paging.Limit == 0 {
p.Paging.Limit = defLimit
}
// page
if p.Paging.Page < 1 {
p.Paging.Page = defPage
} else if p.Paging.Page > 1 {
offset = (p.Paging.Page - 1) * p.Paging.Limit
}
// sort
if len(p.Paging.OrderBy) > 0 {
for _, o := range p.Paging.OrderBy {
db = db.Order(o)
}
} else {
str := "id desc"
p.Paging.OrderBy = append(p.Paging.OrderBy, str)
}
// get
if errGet := db.Limit(p.Paging.Limit).Offset(offset).Find(result).Error; errGet != nil && !errors.Is(errGet, gorm.ErrRecordNotFound) {
return nil, errGet
}
<-done
// total pages
total := int(math.Ceil(float64(count) / float64(p.Paging.Limit)))
// construct pagination
paginator = &Pagination{
TotalRecords: count,
Page: p.Paging.Page,
Offset: offset,
Limit: p.Paging.Limit,
TotalPage: total,
PrevPage: p.Paging.Page,
NextPage: p.Paging.Page,
}
// prev page
if p.Paging.Page > 1 {
paginator.PrevPage = p.Paging.Page - 1
}
// next page
if p.Paging.Page != paginator.TotalPage {
paginator.NextPage = p.Paging.Page + 1
}
return paginator, nil
}
func getCounts(db *gorm.DB, anyType interface{}, done chan bool, count *int64) {
db.Model(anyType).Count(count)
done <- true
}
func (p Pagination) IsEmpty() bool {
return p.TotalRecords <= 0
}