sort items asc/desc

This commit is contained in:
Nazar Kanaev 2020-07-27 20:52:40 +01:00
parent ed7aace6ff
commit dc91b94cfa
5 changed files with 30 additions and 5 deletions

View File

@ -332,7 +332,8 @@ func ItemListHandler(rw http.ResponseWriter, req *http.Request) {
if search := query.Get("search"); len(search) != 0 { if search := query.Get("search"); len(search) != 0 {
filter.Search = &search filter.Search = &search
} }
items := db(req).ListItems(filter, (curPage-1)*perPage, perPage) newestFirst := query.Get("oldest_first") != "true"
items := db(req).ListItems(filter, (curPage-1)*perPage, perPage, newestFirst)
count := db(req).CountItems(filter) count := db(req).CountItems(filter)
writeJSON(rw, map[string]interface{}{ writeJSON(rw, map[string]interface{}{
"page": map[string]int{ "page": map[string]int{

View File

@ -131,9 +131,13 @@ func listQueryPredicate(filter ItemFilter) (string, []interface{}) {
return predicate, args return predicate, args
} }
func (s *Storage) ListItems(filter ItemFilter, offset, limit int) []Item { func (s *Storage) ListItems(filter ItemFilter, offset, limit int, newestFirst bool) []Item {
predicate, args := listQueryPredicate(filter) predicate, args := listQueryPredicate(filter)
result := make([]Item, 0, 0) result := make([]Item, 0, 0)
order := "desc"
if !newestFirst {
order = "asc"
}
query := fmt.Sprintf(` query := fmt.Sprintf(`
select select
i.id, i.guid, i.feed_id, i.title, i.link, i.description, i.id, i.guid, i.feed_id, i.title, i.link, i.description,
@ -141,9 +145,9 @@ func (s *Storage) ListItems(filter ItemFilter, offset, limit int) []Item {
from items i from items i
join feeds f on f.id = i.feed_id join feeds f on f.id = i.feed_id
where %s where %s
order by i.date desc order by i.date %s
limit %d offset %d limit %d offset %d
`, predicate, limit, offset) `, predicate, order, limit, offset)
rows, err := s.db.Query(query, args...) rows, err := s.db.Query(query, args...)
if err != nil { if err != nil {
s.log.Print(err) s.log.Print(err)

View File

@ -8,6 +8,7 @@ func settingsDefaults() map[string]interface{} {
"feed": "", "feed": "",
"feed_list_width": 300, "feed_list_width": 300,
"item_list_width": 300, "item_list_width": 300,
"sort_newest_first": true,
} }
} }

View File

@ -23,11 +23,21 @@
<span class="icon mr-1">{% inline "plus.svg" %}</span> <span class="icon mr-1">{% inline "plus.svg" %}</span>
New Feed New Feed
</b-dropdown-item-button> </b-dropdown-item-button>
<b-dropdown-item-button @click="showSettings('manage')"> <b-dropdown-item-button @click.stop="showSettings('manage')">
<span class="icon mr-1">{% inline "list.svg" %}</span> <span class="icon mr-1">{% inline "list.svg" %}</span>
Manage Feeds Manage Feeds
</b-dropdown-item-button> </b-dropdown-item-button>
<b-dropdown-divider></b-dropdown-divider> <b-dropdown-divider></b-dropdown-divider>
<b-dropdown-header>Sort by</b-dropdown-header>
<b-dropdown-item-button @click.stop="itemSortNewestFirst=true">
<span class="icon mr-1" :class="{invisible: !itemSortNewestFirst}">{% inline "check.svg" %}</span>
Newest First
</b-dropdown-item-button>
<b-dropdown-item-button @click="itemSortNewestFirst=false">
<span class="icon mr-1" :class="{invisible: itemSortNewestFirst}">{% inline "check.svg" %}</span>
Oldest First
</b-dropdown-item-button>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-form id="opml-import-form" enctype="multipart/form-data"> <b-dropdown-form id="opml-import-form" enctype="multipart/form-data">
<input type="file" <input type="file"
id="opml-import" id="opml-import"

View File

@ -59,6 +59,7 @@ var vm = new Vue({
api.settings.get().then(function(data) { api.settings.get().then(function(data) {
vm.feedSelected = data.feed vm.feedSelected = data.feed
vm.filterSelected = data.filter vm.filterSelected = data.filter
vm.itemSortNewestFirst = data.sort_newest_first
vm.refreshItems() vm.refreshItems()
}) })
this.refreshFeeds() this.refreshFeeds()
@ -79,6 +80,7 @@ var vm = new Vue({
'itemSelectedDetails': {}, 'itemSelectedDetails': {},
'itemSelectedReadability': '', 'itemSelectedReadability': '',
'itemSearch': '', 'itemSearch': '',
'itemSortNewestFirst': null,
'settings': 'create', 'settings': 'create',
'loading': { 'loading': {
'newfeed': false, 'newfeed': false,
@ -161,6 +163,10 @@ var vm = new Vue({
this.refreshItems() this.refreshItems()
} }
}, 500), }, 500),
'itemSortNewestFirst': function(newVal, oldVal) {
if (oldVal === null) return
api.settings.update({sort_newest_first: newVal}).then(this.refreshItems.bind(this))
},
}, },
methods: { methods: {
refreshStats: function() { refreshStats: function() {
@ -190,6 +196,9 @@ var vm = new Vue({
if (this.itemSearch) { if (this.itemSearch) {
query.search = this.itemSearch query.search = this.itemSearch
} }
if (!this.itemSortNewestFirst) {
query.oldest_first = true
}
return query return query
}, },
refreshFeeds: function() { refreshFeeds: function() {