From d01060ba3bdbd7d287818c47cb2c038dcc13c1b0 Mon Sep 17 00:00:00 2001 From: Nazar Kanaev Date: Sun, 5 Jul 2020 20:19:03 +0100 Subject: [PATCH] list all/folder/feed items --- server/handlers.go | 25 +++++++++++- server/server.go | 2 + storage/item.go | 62 +++++++++++++++++------------- template/static/javascripts/api.js | 6 +++ template/static/javascripts/app.js | 24 +++++++----- 5 files changed, 83 insertions(+), 36 deletions(-) diff --git a/server/handlers.go b/server/handlers.go index 6b152ff..3bac4fb 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -263,7 +263,7 @@ func FeedItemsHandler(rw http.ResponseWriter, req *http.Request) { return } rw.WriteHeader(http.StatusOK) - items := db(req).ListFeedItems(id) + items := db(req).ListItems(storage.ItemFilter{FeedID: &id}) writeJSON(rw, items) } @@ -292,3 +292,26 @@ func ItemHandler(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(http.StatusMethodNotAllowed) } } + +func FolderItemsHandler(rw http.ResponseWriter, req *http.Request) { + if req.Method == "GET" { + id, err := strconv.ParseInt(Vars(req)["id"], 10, 64) + if err != nil { + rw.WriteHeader(http.StatusBadRequest) + return + } + items := db(req).ListItems(storage.ItemFilter{FolderID: &id}) + writeJSON(rw, items) + } else { + rw.WriteHeader(http.StatusMethodNotAllowed) + } +} + +func ItemListHandler(rw http.ResponseWriter, req *http.Request) { + if req.Method == "GET" { + items := db(req).ListItems(storage.ItemFilter{}) + writeJSON(rw, items) + } else { + rw.WriteHeader(http.StatusMethodNotAllowed) + } +} diff --git a/server/server.go b/server/server.go index 740a712..be34468 100644 --- a/server/server.go +++ b/server/server.go @@ -73,10 +73,12 @@ var routes []Route = []Route{ p("/api/status", StatusHandler), p("/api/folders", FolderListHandler), p("/api/folders/:id", FolderHandler), + p("/api/folders/:id/items", FolderItemsHandler), p("/api/feeds", FeedListHandler), p("/api/feeds/:id", FeedHandler), p("/api/feeds/:id/items", FeedItemsHandler), p("/api/feeds/find", FeedHandler), + p("/api/items", ItemListHandler), p("/api/items/:id", ItemHandler), } diff --git a/storage/item.go b/storage/item.go index 584f662..56ff443 100644 --- a/storage/item.go +++ b/storage/item.go @@ -3,6 +3,7 @@ package storage import ( "fmt" "time" + "strings" "encoding/json" ) @@ -54,6 +55,12 @@ type Item struct { Image string `json:"image"` } +type ItemFilter struct { + FolderID *int64 + FeedID *int64 + Status *ItemStatus +} + func (s *Storage) CreateItems(items []Item) bool { tx, err := s.db.Begin() if err != nil { @@ -89,15 +96,38 @@ func (s *Storage) CreateItems(items []Item) bool { return true } -func itemQuery(s *Storage, cond string, v ...interface{}) []Item { +func (s *Storage) ListItems(filter ItemFilter) []Item { + cond := make([]string, 0) + args := make([]interface{}, 0) + if filter.FolderID != nil { + cond = append(cond, "f.folder_id = ?") + args = append(args, *filter.FolderID) + } + if filter.FeedID != nil { + cond = append(cond, "i.feed_id = ?") + args = append(args, *filter.FeedID) + } + if filter.Status != nil { + cond = append(cond, "i.status = ?") + args = append(args, *filter.Status) + } + + predicate := "1" + if len(cond) > 0 { + predicate = strings.Join(cond, " and ") + } + result := make([]Item, 0, 0) query := fmt.Sprintf(` select - id, guid, feed_id, title, link, description, - content, author, date, date_updated, status, image - from items - where %s`, cond) - rows, err := s.db.Query(query, v...) + i.id, i.guid, i.feed_id, i.title, i.link, i.description, + i.content, i.author, i.date, i.date_updated, i.status, i.image + from items i + join feeds f on f.id = i.feed_id + where %s + order by i.date desc + `, predicate) + rows, err := s.db.Query(query, args...) if err != nil { s.log.Print(err) return result @@ -127,26 +157,6 @@ func itemQuery(s *Storage, cond string, v ...interface{}) []Item { return result } -func (s *Storage) ListItems() []Item { - return itemQuery(s, `1`) -} - -func (s *Storage) ListFolderItems(folder_id int64) []Item { - return itemQuery(s, `folder_id = ?`, folder_id) -} - -func (s *Storage) ListFolderItemsFiltered(folder_id int64, status ItemStatus) []Item { - return itemQuery(s, `folder_id = ? and status = ?`, folder_id, status) -} - -func (s *Storage) ListFeedItems(feed_id int64) []Item { - return itemQuery(s, `feed_id = ?`, feed_id) -} - -func (s *Storage) ListFeedItemsFiltered(feed_id int64, status ItemStatus) []Item { - return itemQuery(s, `feed_id = ? and status = ?`, feed_id, status) -} - 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 diff --git a/template/static/javascripts/api.js b/template/static/javascripts/api.js index 5200d3a..3044f8d 100644 --- a/template/static/javascripts/api.js +++ b/template/static/javascripts/api.js @@ -44,8 +44,14 @@ delete: function(id) { return api('delete', '/api/folders/' + id) }, + list_items: function(id) { + return api('get', '/api/folders/' + id + '/items').then(json) + } }, items: { + list: function() { + return api('get', '/api/items').then(json) + }, update: function(id, data) { return api('put', '/api/items/' + id, data) } diff --git a/template/static/javascripts/app.js b/template/static/javascripts/app.js index 32fbe2a..a2b08d2 100644 --- a/template/static/javascripts/app.js +++ b/template/static/javascripts/app.js @@ -42,16 +42,22 @@ var vm = new Vue({ }, watch: { 'feedSelected': function(newVal, oldVal) { - if (newVal === null) return - var vm = this - var parts = newVal.split(':', 2) - var type = parts[0] - var guid = parts[1] - if (type === 'feed') { - api.feeds.list_items(guid).then(function(items) { - vm.items = items - }) + var promise = null + if (newVal === null) { + promise = api.items.list() + } else { + var parts = newVal.split(':', 2) + var type = parts[0] + var guid = parts[1] + if (type === 'feed') { + promise = api.feeds.list_items(guid) + } else if (type == 'folder') { + promise = api.folders.list_items(guid) + } } + promise.then(function(items) { + vm.items = items + }) }, 'itemSelected': function(newVal, oldVal) { this.itemSelectedDetails = this.itemsById[newVal]