diff --git a/server/handlers.go b/server/handlers.go index 58a93a4..6b152ff 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -184,7 +184,7 @@ func convertItems(items []*gofeed.Item, feed storage.Feed) []storage.Item { author = item.Author.Name } result = append(result, storage.Item{ - Id: item.GUID, + GUID: item.GUID, FeedId: feed.Id, Title: item.Title, Link: item.Link, @@ -266,3 +266,29 @@ func FeedItemsHandler(rw http.ResponseWriter, req *http.Request) { items := db(req).ListFeedItems(id) writeJSON(rw, items) } + +type UpdateItem struct { + Status *storage.ItemStatus `json:"status,omitempty"` +} + +func ItemHandler(rw http.ResponseWriter, req *http.Request) { + if req.Method == "PUT" { + id, err := strconv.ParseInt(Vars(req)["id"], 10, 64) + if err != nil { + rw.WriteHeader(http.StatusBadRequest) + return + } + var body UpdateItem + if err := json.NewDecoder(req.Body).Decode(&body); err != nil { + log.Print(err) + rw.WriteHeader(http.StatusBadRequest) + return + } + if body.Status != nil { + db(req).UpdateItemStatus(id, *body.Status) + } + rw.WriteHeader(http.StatusOK) + } else { + rw.WriteHeader(http.StatusMethodNotAllowed) + } +} diff --git a/server/server.go b/server/server.go index e496e39..740a712 100644 --- a/server/server.go +++ b/server/server.go @@ -77,6 +77,7 @@ var routes []Route = []Route{ p("/api/feeds/:id", FeedHandler), p("/api/feeds/:id/items", FeedItemsHandler), p("/api/feeds/find", FeedHandler), + p("/api/items/:id", ItemHandler), } func Vars(req *http.Request) map[string]string { diff --git a/storage/item.go b/storage/item.go index 8b2400b..584f662 100644 --- a/storage/item.go +++ b/storage/item.go @@ -32,7 +32,7 @@ func (s ItemStatus) MarshalJSON() ([]byte, error) { func (s *ItemStatus) UnmarshalJSON(b []byte) error { var str string - if err := json.Unmarshal(b, &s); err != nil { + if err := json.Unmarshal(b, &str); err != nil { return err } *s = StatusValues[str] @@ -40,7 +40,8 @@ func (s *ItemStatus) UnmarshalJSON(b []byte) error { } type Item struct { - Id string `json:"id"` + Id int64 `json:"id"` + GUID string `json:"guid"` FeedId int64 `json:"feed_id"` Title string `json:"title"` Link string `json:"link"` @@ -62,12 +63,12 @@ func (s *Storage) CreateItems(items []Item) bool { for _, item := range items { _, err = tx.Exec(` insert into items ( - id, feed_id, title, link, description, + guid, feed_id, title, link, description, content, author, date, date_updated, status, image ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - on conflict (id) do update set date_updated=?`, - item.Id, item.FeedId, item.Title, item.Link, item.Description, + on conflict (guid) do update set date_updated=?`, + item.GUID, item.FeedId, item.Title, item.Link, item.Description, item.Content, item.Author, item.Date, item.DateUpdated, UNREAD, item.Image, // upsert values item.DateUpdated, @@ -92,7 +93,7 @@ func itemQuery(s *Storage, cond string, v ...interface{}) []Item { result := make([]Item, 0, 0) query := fmt.Sprintf(` select - id, feed_id, title, link, description, + id, guid, feed_id, title, link, description, content, author, date, date_updated, status, image from items where %s`, cond) @@ -105,6 +106,7 @@ func itemQuery(s *Storage, cond string, v ...interface{}) []Item { var x Item err = rows.Scan( &x.Id, + &x.GUID, &x.FeedId, &x.Title, &x.Link, @@ -144,3 +146,8 @@ func (s *Storage) ListFeedItems(feed_id int64) []Item { 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/storage/storage.go b/storage/storage.go index e917913..92085c3 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -28,7 +28,8 @@ create index if not exists idx_feed_folder_id on feeds(folder_id); create unique index if not exists idx_feed_feed_link on feeds(feed_link); create table if not exists items ( - id string primary key, + id integer primary key autoincrement, + guid string not null, feed_id references feeds(id), title text, link text, @@ -43,6 +44,7 @@ create table if not exists items ( create index if not exists idx_item_feed_id on items(feed_id); create index if not exists idx_item_status on items(status); +create unique index if not exists idx_item_guid on items(guid); ` type Storage struct { diff --git a/template/static/javascripts/api.js b/template/static/javascripts/api.js index 2a05f09..5200d3a 100644 --- a/template/static/javascripts/api.js +++ b/template/static/javascripts/api.js @@ -45,5 +45,10 @@ return api('delete', '/api/folders/' + id) }, }, + items: { + 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 cd566f6..32fbe2a 100644 --- a/template/static/javascripts/app.js +++ b/template/static/javascripts/app.js @@ -57,6 +57,7 @@ var vm = new Vue({ this.itemSelectedDetails = this.itemsById[newVal] if (this.itemSelectedDetails.status == 'unread') { this.itemSelectedDetails.status = 'read' + api.items.update(this.itemSelectedDetails.id, {status: this.itemSelectedDetails.status}) } }, }, @@ -150,6 +151,7 @@ var vm = new Vue({ } else if (item.status != 'starred') { item.status = 'starred' } + api.items.update(item.id, {status: item.status}) }, toggleItemRead: function(item) { if (item.status == 'unread') { @@ -157,6 +159,7 @@ var vm = new Vue({ } else if (item.status == 'read') { item.status = 'unread' } + api.items.update(item.id, {status: item.status}) }, } })