github.com/seeker-insurance/kit@v0.0.13/web/pagination/pagination.go (about) 1 package pagination 2 3 import ( 4 "math" 5 "strconv" 6 7 "net/url" 8 9 "github.com/jinzhu/gorm" 10 "github.com/labstack/echo" 11 ) 12 13 type ( 14 Pagination struct { 15 Count int `json:"item_count"` 16 Max int `json:"max"` 17 Page int `json:"page"` 18 PerPage int 19 Offset int 20 Url url.URL 21 } 22 ) 23 24 func (p *Pagination) Links() map[string]string { 25 pageValues := map[string]int{"self": p.Page} 26 27 if p.Max != 1 { 28 pageValues["first"] = 1 29 pageValues["last"] = p.Max 30 } 31 32 if p.Max != p.Page { 33 pageValues["next"] = p.Page + 1 34 } 35 36 if p.Page > 1 { 37 pageValues["prev"] = p.Page - 1 38 } 39 40 return p.linkify(pageValues) 41 } 42 43 func (p Pagination) linkify(pageValues map[string]int) map[string]string { 44 links := make(map[string]string) 45 for k, v := range pageValues { 46 links[k] = p.withPageNumber(v) 47 } 48 return links 49 } 50 51 func (p Pagination) withPageNumber(num int) string { 52 q := p.Url.Query() 53 q.Set("page[number]", strconv.Itoa(num)) 54 p.Url.RawQuery = q.Encode() 55 56 return p.Url.RequestURI() 57 } 58 59 // DefaultPerPage ... 60 var DefaultPerPage = 20 61 62 // MaxPerPage ... 63 var MaxPerPage = 100 64 65 // Data pagination data for jsonapi 66 var Data Pagination 67 68 // Apply apply pagination to a provided scope 69 func Apply(c echo.Context, scope *gorm.DB, model interface{}, list interface{}, perPage int) error { 70 page, _ := strconv.Atoi(c.QueryParam("page")) 71 if page == 0 { 72 page = 1 73 } 74 75 var count int 76 if err := scope.Offset(0).Model(model).Count(&count).Error; err != nil { 77 return err 78 } 79 80 strPerPage := c.QueryParam("per_page") 81 if strPerPage != "" { 82 perPage, _ = strconv.Atoi(strPerPage) 83 } else if perPage == 0 { 84 perPage = DefaultPerPage 85 } 86 87 if perPage > MaxPerPage { 88 perPage = MaxPerPage 89 } 90 91 setData(count, perPage, page) 92 93 if err := scope.Offset(offset(page, perPage)).Limit(perPage). 94 Find(list).Error; err != nil { 95 return err 96 } 97 98 return nil 99 } 100 101 func setData(count int, perPage int, page int) { 102 Data.Count = count 103 pages := float64(count) / float64(perPage) 104 Data.Max = int(math.Ceil(pages)) 105 Data.Page = page 106 } 107 108 func offset(pageNumber int, perPage int) int { 109 return (pageNumber - 1) * perPage 110 }