-
Notifications
You must be signed in to change notification settings - Fork 9
/
pagination.go
132 lines (110 loc) · 2.54 KB
/
pagination.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package codeship
import (
"net/url"
"strconv"
)
type pagination struct {
Total int `json:"total,omitempty"`
PerPage int `json:"per_page,omitempty"`
Page int `json:"page,omitempty"`
}
// PaginationOption is a functional option for providing pagination options
type PaginationOption func(o *paginationOption)
type paginationOption struct {
perPage int
page int
}
// Page sets the page of results to be returned in the response
func Page(page int) PaginationOption {
return func(o *paginationOption) {
o.page = page
}
}
// PerPage sets the number of results to be returned per page in the response
func PerPage(perPage int) PaginationOption {
return func(o *paginationOption) {
o.perPage = perPage
}
}
func paginate(path string, opts ...PaginationOption) (string, error) {
if len(opts) == 0 {
return path, nil
}
opt := &paginationOption{}
for _, f := range opts {
f(opt)
}
u, err := url.Parse(path)
if err != nil {
return path, err
}
q := u.Query()
if opt.page > 0 {
q.Add("page", strconv.Itoa(opt.page))
}
if opt.perPage > 0 {
q.Add("per_page", strconv.Itoa(opt.perPage))
}
u.RawQuery = q.Encode()
return u.String(), nil
}
// Links contain links for pagination purposes
//
// Codeship API docs: https://apidocs.codeship.com/v2/introduction/pagination
type Links struct {
Next string
Previous string
Last string
First string
}
// NextPage returns the page number of the next page
func (l Links) NextPage() (int, error) {
if l.Next == "" {
return 0, nil
}
return pageForURL(l.Next)
}
// PreviousPage returns the page number of the previous page
func (l Links) PreviousPage() (int, error) {
if l.Previous == "" {
return 0, nil
}
return pageForURL(l.Previous)
}
// CurrentPage returns the page number of the current page
func (l Links) CurrentPage() (int, error) {
switch {
case l.Previous == "" && l.Next != "":
return 1, nil
case l.Previous != "":
prevPage, err := pageForURL(l.Previous)
if err != nil {
return 0, err
}
return prevPage + 1, nil
}
return 0, nil
}
// LastPage returns the page number of the last page
func (l Links) LastPage() (int, error) {
if l.Last == "" {
return l.CurrentPage()
}
return pageForURL(l.Last)
}
// IsLastPage returns true if the current page is the last
func (l Links) IsLastPage() bool {
return l.Last == ""
}
func pageForURL(path string) (int, error) {
u, err := url.ParseRequestURI(path)
if err != nil {
return 0, err
}
pageStr := u.Query().Get("page")
page, err := strconv.Atoi(pageStr)
if err != nil {
return 0, err
}
return page, nil
}