golift.io/starr@v1.0.0/paginate.go (about)

     1  package starr
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strconv"
     7  	"strings"
     8  )
     9  
    10  /* This file containers helper methods and types for page-able API calls.
    11   * Like GetHistory() and GetQueue().
    12   */
    13  
    14  // PageReq is the input to search requests that have page-able responses.
    15  // These are turned into HTTP parameters.
    16  type PageReq struct {
    17  	PageSize   int       // 10 is default if not provided.
    18  	Page       int       // 1 is default if not provided.
    19  	SortKey    string    // date, timeleft, others?
    20  	SortDir    Sorting   // ascending, descending
    21  	Filter     Filtering // enums for eventTypes. App specific.
    22  	url.Values           // Additional values that may be set.
    23  }
    24  
    25  // Sorting is used as a request parameter value to sort lists, like History and Queue.
    26  type Sorting string
    27  
    28  const (
    29  	// SortAsc is the default, and sorts lists in ascending order.
    30  	SortAscend Sorting = "ascending"
    31  	// SortDesc flips the sort order to descending.
    32  	SortDescend Sorting = "descending"
    33  )
    34  
    35  // Filtering is used as a request parameter value to filter lists, like History and Queue.
    36  // The filter values are different per-app, so find their values in their respective modules.
    37  type Filtering int
    38  
    39  // Set makes sure the sort direction is valid.
    40  func (s *Sorting) Set(val string) {
    41  	switch Sorting(strings.ToLower(val)) {
    42  	default:
    43  		fallthrough
    44  	case SortAscend:
    45  		*s = SortAscend
    46  	case SortDescend:
    47  		*s = SortDescend
    48  	}
    49  }
    50  
    51  // Param returns the string value of a Filter eventType.
    52  func (f Filtering) Param() string {
    53  	return fmt.Sprint(f)
    54  }
    55  
    56  // Params returns a brand new url.Values with all request parameters combined.
    57  func (r *PageReq) Params() url.Values {
    58  	params := make(url.Values)
    59  
    60  	if r.Filter > 0 {
    61  		params.Set("eventType", r.Filter.Param())
    62  	}
    63  
    64  	if r.Page > 0 {
    65  		params.Set("page", fmt.Sprint(r.Page))
    66  	} else {
    67  		params.Set("page", "1")
    68  	}
    69  
    70  	if r.PageSize > 0 {
    71  		params.Set("pageSize", fmt.Sprint(r.PageSize))
    72  	} else {
    73  		params.Set("pageSize", "10")
    74  	}
    75  
    76  	if r.SortKey != "" {
    77  		params.Set("sortKey", r.SortKey)
    78  	} else {
    79  		params.Set("sortKey", "date") // timeleft, title, id
    80  	}
    81  
    82  	if r.SortDir != "" {
    83  		params.Set("sortDirection", string(r.SortDir))
    84  	} else {
    85  		params.Set("sortDirection", "ascending") // descending
    86  	}
    87  
    88  	for k, v := range r.Values {
    89  		for _, val := range v {
    90  			params.Set(k, val)
    91  		}
    92  	}
    93  
    94  	return params
    95  }
    96  
    97  // Encode turns our request parameters into a URI string.
    98  func (r *PageReq) Encode() string {
    99  	return r.Params().Encode()
   100  }
   101  
   102  // CheckSet sets a request parameter if it's not already set.
   103  func (r *PageReq) CheckSet(key, value string) { //nolint:cyclop
   104  	switch strings.ToLower(key) {
   105  	case "page":
   106  		if r.Page == 0 {
   107  			r.Page, _ = strconv.Atoi(value)
   108  		}
   109  	case "pagesize":
   110  		if r.PageSize == 0 {
   111  			r.PageSize, _ = strconv.Atoi(value)
   112  		}
   113  	case "sortkey":
   114  		if r.SortKey == "" {
   115  			r.SortKey = value
   116  		}
   117  	case "sortdirection":
   118  		if r.SortDir == "" {
   119  			r.SortDir.Set(value)
   120  		}
   121  	default:
   122  		if r.Values == nil {
   123  			r.Values = make(url.Values)
   124  		}
   125  
   126  		if r.Values.Get(key) == "" {
   127  			r.Values.Set(key, value)
   128  		}
   129  	}
   130  }
   131  
   132  // Set sets a request parameter.
   133  func (r *PageReq) Set(key, value string) {
   134  	switch strings.ToLower(key) {
   135  	case "page":
   136  		r.Page, _ = strconv.Atoi(value)
   137  	case "pagesize":
   138  		r.PageSize, _ = strconv.Atoi(value)
   139  	case "sortkey":
   140  		r.SortKey = value
   141  	case "sortdirection":
   142  		r.SortDir.Set(value)
   143  	default:
   144  		if r.Values == nil {
   145  			r.Values = make(url.Values)
   146  		}
   147  
   148  		r.Values.Set(key, value)
   149  	}
   150  }
   151  
   152  // SetPerPage returns a proper perPage value that is not equal to zero,
   153  // and not larger than the record count desired. If the count is zero, then
   154  // perPage can be anything other than zero.
   155  // This is used by paginated methods in the starr modules.
   156  func SetPerPage(records, perPage int) int {
   157  	const perPageDefault = 500
   158  
   159  	if perPage <= 1 {
   160  		if records > perPageDefault || records == 0 {
   161  			perPage = perPageDefault
   162  		} else {
   163  			perPage = records
   164  		}
   165  	} else if perPage > records && records != 0 {
   166  		perPage = records
   167  	}
   168  
   169  	return perPage
   170  }
   171  
   172  // AdjustPerPage to make sure we don't go over, or ask for more records than exist.
   173  // This is used by paginated methods in the starr modules.
   174  // 'records' is the number requested, 'total' is the number in the app,
   175  // 'collected' is how many we have so far, and 'perPage' is the current perPage setting.
   176  func AdjustPerPage(records, total, collected, perPage int) int {
   177  	// Do not ask for more than was requested.
   178  	if d := records - collected; perPage > d && d > 0 {
   179  		perPage = d
   180  	}
   181  
   182  	// Ask for only the known total.
   183  	if d := total - collected; perPage > d {
   184  		perPage = d
   185  	}
   186  
   187  	return perPage
   188  }