forked from zeebo/admin
/
list.go
113 lines (100 loc) · 2.54 KB
/
list.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
package admin
import (
"fmt"
"launchpad.net/mgo"
"net/url"
"strconv"
"strings"
)
//grabInt is a simple handler for grabbing an integer out of a url.Values
//with a default value if there are any errors
func grabInt(v url.Values, key string, def int) int {
val := v.Get(key)
n, err := strconv.ParseInt(val, 10, 0)
if err != nil || n < 0 {
return def
}
return int(n)
}
//listParse takes a collection and some query values and generates an iterator
//for the objects that should be returned on that page
func listParse(c *mgo.Collection, v url.Values) (*mgo.Iter, int, int) {
//parse out sorting
sort := map[string]int{}
for key, _ := range v {
val := v.Get(key)
if len(key) > 5 && strings.HasPrefix(key, "sort_") {
field := key[5:]
switch strings.ToLower(val) {
case "asc":
sort[field] = 1
case "desc":
sort[field] = -1
}
}
}
//set up the query with the correct sort order
query := c.Find(nil).Sort(sort)
//pagination
page, numpage := grabInt(v, "page", 0), grabInt(v, "numpage", 20)
if page < 1 {
page = 1
}
if numpage < 1 {
numpage = 1
}
//pages are 1 indexed.
query = query.Skip(numpage * (page - 1)).Limit(numpage)
return query.Iter(), page, numpage
}
//Pagination helps generate lists of pages for the List view.
type Pagination struct {
Pages int
CurrentPage int
query url.Values
}
//PageList returns a list of integers of size n around the current page. For example
//
// p := Pagination{8, 4}
// p.PageList(5) => []int{1,2,3,4,5,6,7,8}
func (p Pagination) PageList(n int) []int {
bottom, top := p.CurrentPage-n, p.CurrentPage+n
if bottom < 1 {
bottom = 1
}
if top > p.Pages {
top = p.Pages
}
ints := make([]int, 0, top-bottom+1)
for i := bottom; i <= top; i++ {
ints = append(ints, i)
}
return ints
}
//IsCurrent helps you determine if a given page number is the current page in
//templates.
func (p Pagination) IsCurrent(page int) bool {
return page == p.CurrentPage
}
//Next returns the numerical value of the next page. It returns 0 if it would be
//past the last page.
func (p Pagination) Next() int {
if p.CurrentPage >= p.Pages {
return 0
}
return p.CurrentPage + 1
}
//Prev returns the numerical value of the previous page. It returns 0 if it would
//be before the fist page.
func (p Pagination) Prev() int {
if p.CurrentPage <= 1 {
return 0
}
return p.CurrentPage - 1
}
//Page adds the requested page to the passed in url.Values and returns the
//encoded result.
func (p Pagination) Page(n int) string {
p.query.Set("page", fmt.Sprint(n))
return "?" + p.query.Encode()
}