github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/api/util/page.go (about) 1 package util 2 3 import ( 4 "net/http" 5 "net/url" 6 "strconv" 7 ) 8 9 var ( 10 // DefaultPageSize is the number NewPage 11 DefaultPageSize = 50 12 // DefaultMaxPageSize is the max size a page can be by default, set to -1 to 13 // ignore maximum sizes 14 DefaultMaxPageSize = 100 15 ) 16 17 // Page represents pagination information 18 type Page struct { 19 Number int `json:"page,omitempty"` 20 Size int `json:"pageSize,omitempty"` 21 ResultCount int `json:"resultCount,omitempty"` 22 NextURL string `json:"nextUrl"` 23 PrevURL string `json:"prevUrl"` 24 } 25 26 // NewPage constructs a basic page struct, setting sensible defaults 27 func NewPage(number, size int) Page { 28 if number <= 0 { 29 number = 1 30 } 31 32 if DefaultMaxPageSize != -1 && size > DefaultMaxPageSize { 33 size = DefaultMaxPageSize 34 } 35 36 return Page{ 37 Number: number, 38 Size: size, 39 } 40 } 41 42 // Limit is a convenience accessor for page size 43 func (p Page) Limit() int { 44 return p.Size 45 } 46 47 // Offset calculates the starting index for pagination based on page 48 // size & number 49 func (p Page) Offset() int { 50 return (p.Number - 1) * p.Size 51 } 52 53 // Next returns a page with the number advanced by one 54 func (p Page) Next() Page { 55 return Page{ 56 Number: p.Number + 1, 57 Size: p.Size, 58 ResultCount: p.ResultCount, 59 NextURL: p.NextURL, 60 PrevURL: p.PrevURL, 61 } 62 } 63 64 // Prev returns a page with the number decremented by 1 65 func (p Page) Prev() Page { 66 return Page{ 67 Number: p.Number - 1, 68 Size: p.Size, 69 ResultCount: p.ResultCount, 70 NextURL: p.NextURL, 71 PrevURL: p.PrevURL, 72 } 73 } 74 75 // SetQueryParams adds pagination info to a url as query parameters 76 func (p Page) SetQueryParams(u *url.URL) *url.URL { 77 q := u.Query() 78 q.Set("page", strconv.Itoa(p.Number)) 79 if p.Size != DefaultPageSize { 80 q.Set("pageSize", strconv.Itoa(p.Size)) 81 } 82 83 u.RawQuery = q.Encode() 84 return u 85 } 86 87 // NextPageExists returns false if the next page.ResultCount is a postive 88 // number and the starting offset of the next page exceeds page.ResultCount 89 func (p Page) NextPageExists() bool { 90 return p.ResultCount <= 0 || !(p.Number*p.Size >= p.ResultCount) 91 } 92 93 // PrevPageExists returns false if the page number is 1 94 func (p Page) PrevPageExists() bool { 95 return p.Number > 1 96 } 97 98 // PageFromRequest extracts pagination params from an http request 99 func PageFromRequest(r *http.Request) Page { 100 number := ReqParamInt(r, "page", 1) 101 if number <= 0 { 102 number = 1 103 } 104 105 size := ReqParamInt(r, "pageSize", DefaultPageSize) 106 if size <= 0 { 107 size = DefaultPageSize 108 } 109 110 if DefaultMaxPageSize != -1 && size > DefaultMaxPageSize { 111 size = DefaultMaxPageSize 112 } 113 114 return Page{ 115 Number: number, 116 Size: size, 117 } 118 } 119 120 // NewPageFromOffsetAndLimit converts a offset and Limit to a Page struct 121 func NewPageFromOffsetAndLimit(offset, limit int) Page { 122 var number, size int 123 size = limit 124 if size <= 0 { 125 size = DefaultPageSize 126 } 127 number = offset/size + 1 128 return Page{ 129 Number: number, 130 Size: size, 131 } 132 }