mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
fix pagination
This commit is contained in:
parent
7cfd3b3238
commit
7aeb458ee5
@ -260,7 +260,7 @@
|
||||
<div>{{ item.title || 'untitled' }}</div>
|
||||
</div>
|
||||
</label>
|
||||
<button class="btn btn-link btn-block loading my-3" v-if="itemsPage.cur < itemsPage.num"></button>
|
||||
<button class="btn btn-link btn-block loading my-3" v-if="itemsHasMore"></button>
|
||||
</div>
|
||||
<div class="px-3 py-2 border-top text-danger text-break" v-if="feed_errors[current.feed.id]">
|
||||
{{ feed_errors[current.feed.id] }}
|
||||
|
@ -180,7 +180,7 @@ var vm = new Vue({
|
||||
created: function() {
|
||||
this.refreshStats()
|
||||
.then(this.refreshFeeds.bind(this))
|
||||
.then(this.refreshItems.bind(this))
|
||||
.then(this.refreshItems.bind(this, false))
|
||||
|
||||
api.feeds.list_errors().then(function(errors) {
|
||||
vm.feed_errors = errors
|
||||
@ -197,10 +197,7 @@ var vm = new Vue({
|
||||
'feedNewChoice': [],
|
||||
'feedNewChoiceSelected': '',
|
||||
'items': [],
|
||||
'itemsPage': {
|
||||
'cur': 1,
|
||||
'num': 1,
|
||||
},
|
||||
'itemsHasMore': true,
|
||||
'itemSelected': null,
|
||||
'itemSelectedDetails': null,
|
||||
'itemSelectedReadability': '',
|
||||
@ -304,13 +301,13 @@ var vm = new Vue({
|
||||
},
|
||||
'filterSelected': function(newVal, oldVal) {
|
||||
if (oldVal === undefined) return // do nothing, initial setup
|
||||
api.settings.update({filter: newVal}).then(this.refreshItems.bind(this))
|
||||
api.settings.update({filter: newVal}).then(this.refreshItems.bind(this, false))
|
||||
this.itemSelected = null
|
||||
this.computeStats()
|
||||
},
|
||||
'feedSelected': function(newVal, oldVal) {
|
||||
if (oldVal === undefined) return // do nothing, initial setup
|
||||
api.settings.update({feed: newVal}).then(this.refreshItems.bind(this))
|
||||
api.settings.update({feed: newVal}).then(this.refreshItems.bind(this, false))
|
||||
this.itemSelected = null
|
||||
if (this.$refs.itemlist) this.$refs.itemlist.scrollTop = 0
|
||||
},
|
||||
@ -339,7 +336,7 @@ var vm = new Vue({
|
||||
}, 500),
|
||||
'itemSortNewestFirst': function(newVal, oldVal) {
|
||||
if (oldVal === undefined) return // do nothing, initial setup
|
||||
api.settings.update({sort_newest_first: newVal}).then(this.refreshItems.bind(this))
|
||||
api.settings.update({sort_newest_first: newVal}).then(vm.refreshItems.bind(this, false))
|
||||
},
|
||||
'feedListWidth': debounce(function(newVal, oldVal) {
|
||||
if (oldVal === undefined) return // do nothing, initial setup
|
||||
@ -404,34 +401,34 @@ var vm = new Vue({
|
||||
vm.feeds = values[1]
|
||||
})
|
||||
},
|
||||
refreshItems: function() {
|
||||
refreshItems: function(loadMore) {
|
||||
if (this.feedSelected === null) {
|
||||
vm.items = []
|
||||
vm.itemsPage = {'cur': 1, 'num': 1}
|
||||
return
|
||||
}
|
||||
|
||||
var query = this.getItemsQuery()
|
||||
if (loadMore) {
|
||||
query.after = vm.items[vm.items.length-1].id
|
||||
}
|
||||
|
||||
this.loading.items = true
|
||||
return api.items.list(query).then(function(data) {
|
||||
vm.items = data.list
|
||||
vm.itemsPage = data.page
|
||||
if (loadMore) {
|
||||
vm.items = vm.items.concat(data.list)
|
||||
} else {
|
||||
vm.items = data.list
|
||||
}
|
||||
vm.itemsHasMore = data.has_more
|
||||
vm.loading.items = false
|
||||
})
|
||||
},
|
||||
loadMoreItems: function(event, el) {
|
||||
if (this.itemsPage.cur >= this.itemsPage.num) return
|
||||
if (!this.itemsHasMore) 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
|
||||
})
|
||||
}
|
||||
if (closeToBottom) this.refreshItems(true)
|
||||
},
|
||||
markItemsRead: function() {
|
||||
var query = this.getItemsQuery()
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@ -307,11 +306,8 @@ func (s *Server) handleItem(c *router.Context) {
|
||||
func (s *Server) handleItemList(c *router.Context) {
|
||||
if c.Req.Method == "GET" {
|
||||
perPage := 20
|
||||
curPage := 1
|
||||
query := c.Req.URL.Query()
|
||||
if page, err := c.QueryInt64("page"); err == nil {
|
||||
curPage = int(page)
|
||||
}
|
||||
|
||||
filter := storage.ItemFilter{}
|
||||
if folderID, err := c.QueryInt64("folder_id"); err == nil {
|
||||
filter.FolderID = &folderID
|
||||
@ -319,6 +315,9 @@ func (s *Server) handleItemList(c *router.Context) {
|
||||
if feedID, err := c.QueryInt64("feed_id"); err == nil {
|
||||
filter.FeedID = &feedID
|
||||
}
|
||||
if after, err := c.QueryInt64("after"); err == nil {
|
||||
filter.After = &after
|
||||
}
|
||||
if status := query.Get("status"); len(status) != 0 {
|
||||
statusValue := storage.StatusValues[status]
|
||||
filter.Status = &statusValue
|
||||
@ -327,14 +326,16 @@ func (s *Server) handleItemList(c *router.Context) {
|
||||
filter.Search = &search
|
||||
}
|
||||
newestFirst := query.Get("oldest_first") != "true"
|
||||
items := s.db.ListItems(filter, (curPage-1)*perPage, perPage, newestFirst)
|
||||
count := s.db.CountItems(filter)
|
||||
|
||||
items := s.db.ListItems(filter, perPage+1, newestFirst)
|
||||
hasMore := false
|
||||
if len(items) == perPage+1 {
|
||||
hasMore = true
|
||||
items = items[:perPage]
|
||||
}
|
||||
c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"page": map[string]int{
|
||||
"cur": curPage,
|
||||
"num": int(math.Ceil(float64(count) / float64(perPage))),
|
||||
},
|
||||
"list": items,
|
||||
"has_more": hasMore,
|
||||
})
|
||||
} else if c.Req.Method == "PUT" {
|
||||
filter := storage.MarkFilter{}
|
||||
|
@ -61,6 +61,7 @@ type ItemFilter struct {
|
||||
FeedID *int64
|
||||
Status *ItemStatus
|
||||
Search *string
|
||||
After *int64
|
||||
}
|
||||
|
||||
type MarkFilter struct {
|
||||
@ -106,7 +107,7 @@ func (s *Storage) CreateItems(items []Item) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func listQueryPredicate(filter ItemFilter) (string, []interface{}) {
|
||||
func listQueryPredicate(filter ItemFilter, newestFirst bool) (string, []interface{}) {
|
||||
cond := make([]string, 0)
|
||||
args := make([]interface{}, 0)
|
||||
if filter.FolderID != nil {
|
||||
@ -131,6 +132,14 @@ func listQueryPredicate(filter ItemFilter) (string, []interface{}) {
|
||||
cond = append(cond, "i.search_rowid in (select rowid from search where search match ?)")
|
||||
args = append(args, strings.Join(terms, " "))
|
||||
}
|
||||
if filter.After != nil {
|
||||
compare := ">"
|
||||
if newestFirst {
|
||||
compare = "<"
|
||||
}
|
||||
cond = append(cond, fmt.Sprintf("(i.date, i.id) %s (select date, id from items where id = ?)", compare))
|
||||
args = append(args, *filter.After)
|
||||
}
|
||||
|
||||
predicate := "1"
|
||||
if len(cond) > 0 {
|
||||
@ -140,13 +149,13 @@ func listQueryPredicate(filter ItemFilter) (string, []interface{}) {
|
||||
return predicate, args
|
||||
}
|
||||
|
||||
func (s *Storage) ListItems(filter ItemFilter, offset, limit int, newestFirst bool) []Item {
|
||||
predicate, args := listQueryPredicate(filter)
|
||||
func (s *Storage) ListItems(filter ItemFilter, limit int, newestFirst bool) []Item {
|
||||
predicate, args := listQueryPredicate(filter, newestFirst)
|
||||
result := make([]Item, 0, 0)
|
||||
|
||||
order := "date desc"
|
||||
order := "date desc, id desc"
|
||||
if !newestFirst {
|
||||
order = "date asc"
|
||||
order = "date asc, id asc"
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
@ -157,8 +166,8 @@ func (s *Storage) ListItems(filter ItemFilter, offset, limit int, newestFirst bo
|
||||
from items i
|
||||
where %s
|
||||
order by %s
|
||||
limit %d offset %d
|
||||
`, predicate, order, limit, offset)
|
||||
limit %d
|
||||
`, predicate, order, limit)
|
||||
rows, err := s.db.Query(query, args...)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
@ -199,28 +208,13 @@ func (s *Storage) GetItem(id int64) *Item {
|
||||
return i
|
||||
}
|
||||
|
||||
func (s *Storage) CountItems(filter ItemFilter) int64 {
|
||||
predicate, args := listQueryPredicate(filter)
|
||||
query := fmt.Sprintf(`
|
||||
select count(i.id)
|
||||
from items i
|
||||
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
|
||||
}
|
||||
|
||||
func (s *Storage) MarkItemsRead(filter MarkFilter) bool {
|
||||
predicate, args := listQueryPredicate(ItemFilter{FolderID: filter.FolderID, FeedID: filter.FeedID})
|
||||
predicate, args := listQueryPredicate(ItemFilter{FolderID: filter.FolderID, FeedID: filter.FeedID}, false)
|
||||
query := fmt.Sprintf(`
|
||||
update items as i set status = %d
|
||||
where %s and i.status != %d
|
||||
|
Loading…
x
Reference in New Issue
Block a user