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  }