table-pagination.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package vuetifyx
  2. import (
  3. "context"
  4. "fmt"
  5. "sort"
  6. "github.com/qor5/ui/vuetify"
  7. "github.com/qor5/web"
  8. h "github.com/theplant/htmlgo"
  9. )
  10. type VXTablePaginationBuilder struct {
  11. total int64
  12. currPage int64
  13. perPage int64
  14. customPerPages []int64
  15. noPerPagePart bool
  16. onSelectPerPage interface{}
  17. onPrevPage interface{}
  18. onNextPage interface{}
  19. perPageText string
  20. }
  21. func VXTablePagination() *VXTablePaginationBuilder {
  22. return &VXTablePaginationBuilder{}
  23. }
  24. func (tpb *VXTablePaginationBuilder) PerPageText(v string) *VXTablePaginationBuilder {
  25. tpb.perPageText = v
  26. return tpb
  27. }
  28. func (tpb *VXTablePaginationBuilder) Total(v int64) *VXTablePaginationBuilder {
  29. tpb.total = v
  30. return tpb
  31. }
  32. func (tpb *VXTablePaginationBuilder) CurrPage(v int64) *VXTablePaginationBuilder {
  33. tpb.currPage = v
  34. return tpb
  35. }
  36. func (tpb *VXTablePaginationBuilder) PerPage(v int64) *VXTablePaginationBuilder {
  37. tpb.perPage = v
  38. return tpb
  39. }
  40. func (tpb *VXTablePaginationBuilder) CustomPerPages(v []int64) *VXTablePaginationBuilder {
  41. tpb.customPerPages = v
  42. return tpb
  43. }
  44. func (tpb *VXTablePaginationBuilder) NoPerPagePart(v bool) *VXTablePaginationBuilder {
  45. tpb.noPerPagePart = v
  46. return tpb
  47. }
  48. func (tpb *VXTablePaginationBuilder) OnSelectPerPage(v interface{}) *VXTablePaginationBuilder {
  49. tpb.onSelectPerPage = v
  50. return tpb
  51. }
  52. func (tpb *VXTablePaginationBuilder) OnPrevPage(v interface{}) *VXTablePaginationBuilder {
  53. tpb.onPrevPage = v
  54. return tpb
  55. }
  56. func (tpb *VXTablePaginationBuilder) OnNextPage(v interface{}) *VXTablePaginationBuilder {
  57. tpb.onNextPage = v
  58. return tpb
  59. }
  60. func (tpb *VXTablePaginationBuilder) MarshalHTML(ctx context.Context) ([]byte, error) {
  61. if tpb.onSelectPerPage == nil {
  62. tpb.OnSelectPerPage(web.Plaid().
  63. PushState(true).
  64. Query("per_page", web.Var("[$event]")).
  65. MergeQuery(true).
  66. Go())
  67. }
  68. if tpb.onPrevPage == nil {
  69. tpb.OnPrevPage(web.Plaid().
  70. PushState(true).
  71. Query("page", tpb.currPage-1).
  72. MergeQuery(true).
  73. Go())
  74. }
  75. if tpb.onNextPage == nil {
  76. tpb.OnNextPage(web.Plaid().
  77. PushState(true).
  78. Query("page", tpb.currPage+1).
  79. MergeQuery(true).
  80. Go())
  81. }
  82. var sItems []string
  83. {
  84. perPagesM := map[int64]struct{}{
  85. 10: {},
  86. 15: {},
  87. 20: {},
  88. 50: {},
  89. 100: {},
  90. }
  91. if tpb.perPage > 0 {
  92. perPagesM[tpb.perPage] = struct{}{}
  93. }
  94. for _, v := range tpb.customPerPages {
  95. if v <= 0 {
  96. continue
  97. }
  98. perPagesM[v] = struct{}{}
  99. }
  100. perPages := make([]int, 0, len(perPagesM))
  101. for k, _ := range perPagesM {
  102. perPages = append(perPages, int(k))
  103. }
  104. sort.Ints(perPages)
  105. for _, v := range perPages {
  106. sItems = append(sItems, fmt.Sprint(v))
  107. }
  108. }
  109. currPageStart := (tpb.currPage-1)*tpb.perPage + 1
  110. currPageEnd := tpb.currPage * tpb.perPage
  111. if currPageEnd > tpb.total {
  112. currPageEnd = tpb.total
  113. }
  114. canNext := false
  115. canPrev := false
  116. if tpb.currPage*tpb.perPage < tpb.total {
  117. canNext = true
  118. }
  119. if tpb.currPage > 1 {
  120. canPrev = true
  121. }
  122. var nextIconStyle string
  123. var prevIconStyle string
  124. if canNext {
  125. nextIconStyle = "cursor: pointer;"
  126. }
  127. if canPrev {
  128. prevIconStyle = "cursor: pointer;"
  129. }
  130. rowsPerPageText := "Rows per page: "
  131. if tpb.perPageText != "" {
  132. rowsPerPageText = tpb.perPageText
  133. }
  134. return vuetify.VContainer(vuetify.VRow().Justify("end").Align("center").Class("ma-0").
  135. Children(
  136. h.If(!tpb.noPerPagePart,
  137. h.Div(
  138. h.Text(rowsPerPageText),
  139. ),
  140. h.Div(
  141. vuetify.VSelect().Items(sItems).Value(fmt.Sprint(tpb.perPage)).
  142. Attach(false).
  143. HideDetails(true).Class("pt-0 mt-0").
  144. Attr("@input", tpb.onSelectPerPage),
  145. ).Style("width: 60px;").Class("ml-6"),
  146. ),
  147. h.Div(
  148. h.Text(fmt.Sprintf("%d-%d of %d", currPageStart, currPageEnd, tpb.total)),
  149. ).Class("ml-6"),
  150. h.Div(
  151. h.Span("").Style(prevIconStyle).Children(
  152. vuetify.VIcon("navigate_before").Size(32).Disabled(!canPrev).
  153. Attr("@click", tpb.onPrevPage),
  154. ),
  155. h.Span("").Style(nextIconStyle).Children(
  156. vuetify.VIcon("navigate_next").Size(32).Disabled(!canNext).
  157. Attr("@click", tpb.onNextPage),
  158. ).Class("ml-3"),
  159. ).Class("ml-6"),
  160. )).Fluid(true).MarshalHTML(ctx)
  161. }