mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
paginate item list
This commit is contained in:
parent
bc627f5d2c
commit
a203792b1d
@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"math"
|
||||
)
|
||||
|
||||
func IndexHandler(rw http.ResponseWriter, req *http.Request) {
|
||||
@ -287,7 +288,12 @@ func ItemHandler(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
func ItemListHandler(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method == "GET" {
|
||||
perPage := 20
|
||||
curPage := 1
|
||||
query := req.URL.Query()
|
||||
if page, err := strconv.ParseInt(query.Get("page"), 10, 64); err == nil {
|
||||
curPage = int(page)
|
||||
}
|
||||
filter := storage.ItemFilter{}
|
||||
if folderID, err := strconv.ParseInt(query.Get("folder_id"), 10, 64); err == nil {
|
||||
filter.FolderID = &folderID
|
||||
@ -299,9 +305,16 @@ func ItemListHandler(rw http.ResponseWriter, req *http.Request) {
|
||||
statusValue := storage.StatusValues[status]
|
||||
filter.Status = &statusValue
|
||||
}
|
||||
items := db(req).ListItems(filter)
|
||||
items := db(req).ListItems(filter, (curPage-1)*perPage, perPage)
|
||||
count := db(req).CountItems(filter)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
writeJSON(rw, items)
|
||||
writeJSON(rw, map[string]interface{}{
|
||||
"page": map[string]int{
|
||||
"cur": curPage,
|
||||
"num": int(math.Ceil(float64(count) / float64(perPage))),
|
||||
},
|
||||
"list": items,
|
||||
})
|
||||
} else if req.Method == "PUT" {
|
||||
query := req.URL.Query()
|
||||
filter := storage.ItemFilter{}
|
||||
|
@ -96,7 +96,7 @@ func (s *Storage) CreateItems(items []Item) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Storage) ListItems(filter ItemFilter) []Item {
|
||||
func listQueryPredicate(filter ItemFilter) (string, []interface{}) {
|
||||
cond := make([]string, 0)
|
||||
args := make([]interface{}, 0)
|
||||
if filter.FolderID != nil {
|
||||
@ -116,7 +116,11 @@ func (s *Storage) ListItems(filter ItemFilter) []Item {
|
||||
if len(cond) > 0 {
|
||||
predicate = strings.Join(cond, " and ")
|
||||
}
|
||||
return predicate, args
|
||||
}
|
||||
|
||||
func (s *Storage) ListItems(filter ItemFilter, offset, limit int) []Item {
|
||||
predicate, args := listQueryPredicate(filter)
|
||||
result := make([]Item, 0, 0)
|
||||
query := fmt.Sprintf(`
|
||||
select
|
||||
@ -126,7 +130,8 @@ func (s *Storage) ListItems(filter ItemFilter) []Item {
|
||||
join feeds f on f.id = i.feed_id
|
||||
where %s
|
||||
order by i.date desc
|
||||
`, predicate)
|
||||
limit %d offset %d
|
||||
`, predicate, limit, offset)
|
||||
rows, err := s.db.Query(query, args...)
|
||||
if err != nil {
|
||||
s.log.Print(err)
|
||||
@ -157,6 +162,22 @@ func (s *Storage) ListItems(filter ItemFilter) []Item {
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Storage) CountItems(filter ItemFilter) int64 {
|
||||
predicate, args := listQueryPredicate(filter)
|
||||
query := fmt.Sprintf(`
|
||||
select count(i.id)
|
||||
from items i
|
||||
join feeds f on f.id = i.feed_id
|
||||
where %s`, predicate)
|
||||
row := s.db.QueryRow(query, args...)
|
||||
if row != nil {
|
||||
var result int64
|
||||
row.Scan(&result)
|
||||
return result
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *Storage) UpdateItemStatus(item_id int64, status ItemStatus) bool {
|
||||
_, err := s.db.Exec(`update items set status = ? where id = ?`, status, item_id)
|
||||
return err == nil
|
||||
|
@ -77,9 +77,9 @@
|
||||
<img src="./static/images/check.svg" alt="" style="width: 20px; height: 20px;">
|
||||
</button>
|
||||
</div>
|
||||
<div class="p-2 overflow-auto">
|
||||
<div class="p-2 overflow-auto" v-scroll="loadMoreItems">
|
||||
<label v-for="item in items" :key="item.id"
|
||||
class="nav-select mb-1"
|
||||
class="nav-select"
|
||||
:class="{'text-muted' : filterSelected=='all' && item.status=='read',
|
||||
'text-primary': filterSelected=='all' && item.status=='starred'}">
|
||||
<input type="radio" name="item" :value="item.id" v-model="itemSelected">
|
||||
@ -93,6 +93,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<button class="btn btn-link btn-block loading my-3" v-if="itemsPage.cur < itemsPage.num"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vh-100 d-flex flex-column w-100">
|
||||
|
@ -1,5 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
var debounce = function(callback, wait) {
|
||||
var timeout
|
||||
return function() {
|
||||
var context = this, args = arguments
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(function() {
|
||||
callback.apply(this, args)
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
|
||||
Vue.directive('scroll', {
|
||||
inserted: function(el, binding) {
|
||||
el.addEventListener('scroll', debounce(function(event) {
|
||||
binding.value(event, el)
|
||||
}, 200))
|
||||
},
|
||||
})
|
||||
|
||||
var vm = new Vue({
|
||||
el: '#app',
|
||||
created: function() {
|
||||
@ -17,10 +36,17 @@ var vm = new Vue({
|
||||
'feeds': [],
|
||||
'feedSelected': null,
|
||||
'items': [],
|
||||
'itemsPage': {
|
||||
'cur': 1,
|
||||
'num': 1,
|
||||
},
|
||||
'itemSelected': null,
|
||||
'itemSelectedDetails': {},
|
||||
'settings': 'create',
|
||||
'loading': {newfeed: 0},
|
||||
'loading': {
|
||||
'newfeed': false,
|
||||
'items': false,
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -94,10 +120,29 @@ var vm = new Vue({
|
||||
},
|
||||
refreshItems: function() {
|
||||
var query = this.getItemsQuery()
|
||||
api.items.list(query).then(function(items) {
|
||||
vm.items = items
|
||||
this.loading.items = true
|
||||
var vm = this
|
||||
api.items.list(query).then(function(data) {
|
||||
vm.items = data.list
|
||||
vm.itemsPage = data.page
|
||||
vm.loading.items = false
|
||||
})
|
||||
},
|
||||
loadMoreItems: function(event, el) {
|
||||
if (this.itemsPage.cur >= this.itemsPage.num) return
|
||||
if (this.loading.items) return
|
||||
var closeToBottom = (el.scrollHeight - el.scrollTop - el.offsetHeight) < 50
|
||||
if (closeToBottom) {
|
||||
this.loading.moreitems = true
|
||||
var query = this.getItemsQuery()
|
||||
query.page = this.itemsPage.cur + 1
|
||||
api.items.list(query).then(function(data) {
|
||||
vm.items = vm.items.concat(data.list)
|
||||
vm.itemsPage = data.page
|
||||
vm.loading.items = false
|
||||
})
|
||||
}
|
||||
},
|
||||
markItemsRead: function() {
|
||||
var vm = this
|
||||
var query = this.getItemsQuery()
|
||||
|
Loading…
x
Reference in New Issue
Block a user