update item status

This commit is contained in:
Nazar Kanaev 2020-07-05 14:38:50 +01:00
parent 7ecdada4ca
commit 533debf708
6 changed files with 52 additions and 8 deletions

View File

@ -184,7 +184,7 @@ func convertItems(items []*gofeed.Item, feed storage.Feed) []storage.Item {
author = item.Author.Name author = item.Author.Name
} }
result = append(result, storage.Item{ result = append(result, storage.Item{
Id: item.GUID, GUID: item.GUID,
FeedId: feed.Id, FeedId: feed.Id,
Title: item.Title, Title: item.Title,
Link: item.Link, Link: item.Link,
@ -266,3 +266,29 @@ func FeedItemsHandler(rw http.ResponseWriter, req *http.Request) {
items := db(req).ListFeedItems(id) items := db(req).ListFeedItems(id)
writeJSON(rw, items) 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)
}
}

View File

@ -77,6 +77,7 @@ var routes []Route = []Route{
p("/api/feeds/:id", FeedHandler), p("/api/feeds/:id", FeedHandler),
p("/api/feeds/:id/items", FeedItemsHandler), p("/api/feeds/:id/items", FeedItemsHandler),
p("/api/feeds/find", FeedHandler), p("/api/feeds/find", FeedHandler),
p("/api/items/:id", ItemHandler),
} }
func Vars(req *http.Request) map[string]string { func Vars(req *http.Request) map[string]string {

View File

@ -32,7 +32,7 @@ func (s ItemStatus) MarshalJSON() ([]byte, error) {
func (s *ItemStatus) UnmarshalJSON(b []byte) error { func (s *ItemStatus) UnmarshalJSON(b []byte) error {
var str string var str string
if err := json.Unmarshal(b, &s); err != nil { if err := json.Unmarshal(b, &str); err != nil {
return err return err
} }
*s = StatusValues[str] *s = StatusValues[str]
@ -40,7 +40,8 @@ func (s *ItemStatus) UnmarshalJSON(b []byte) error {
} }
type Item struct { type Item struct {
Id string `json:"id"` Id int64 `json:"id"`
GUID string `json:"guid"`
FeedId int64 `json:"feed_id"` FeedId int64 `json:"feed_id"`
Title string `json:"title"` Title string `json:"title"`
Link string `json:"link"` Link string `json:"link"`
@ -62,12 +63,12 @@ func (s *Storage) CreateItems(items []Item) bool {
for _, item := range items { for _, item := range items {
_, err = tx.Exec(` _, err = tx.Exec(`
insert into items ( insert into items (
id, feed_id, title, link, description, guid, feed_id, title, link, description,
content, author, date, date_updated, status, image content, author, date, date_updated, status, image
) )
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
on conflict (id) do update set date_updated=?`, on conflict (guid) do update set date_updated=?`,
item.Id, item.FeedId, item.Title, item.Link, item.Description, item.GUID, item.FeedId, item.Title, item.Link, item.Description,
item.Content, item.Author, item.Date, item.DateUpdated, UNREAD, item.Image, item.Content, item.Author, item.Date, item.DateUpdated, UNREAD, item.Image,
// upsert values // upsert values
item.DateUpdated, item.DateUpdated,
@ -92,7 +93,7 @@ func itemQuery(s *Storage, cond string, v ...interface{}) []Item {
result := make([]Item, 0, 0) result := make([]Item, 0, 0)
query := fmt.Sprintf(` query := fmt.Sprintf(`
select select
id, feed_id, title, link, description, id, guid, feed_id, title, link, description,
content, author, date, date_updated, status, image content, author, date, date_updated, status, image
from items from items
where %s`, cond) where %s`, cond)
@ -105,6 +106,7 @@ func itemQuery(s *Storage, cond string, v ...interface{}) []Item {
var x Item var x Item
err = rows.Scan( err = rows.Scan(
&x.Id, &x.Id,
&x.GUID,
&x.FeedId, &x.FeedId,
&x.Title, &x.Title,
&x.Link, &x.Link,
@ -144,3 +146,8 @@ func (s *Storage) ListFeedItems(feed_id int64) []Item {
func (s *Storage) ListFeedItemsFiltered(feed_id int64, status ItemStatus) []Item { func (s *Storage) ListFeedItemsFiltered(feed_id int64, status ItemStatus) []Item {
return itemQuery(s, `feed_id = ? and status = ?`, feed_id, status) 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
}

View File

@ -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 unique index if not exists idx_feed_feed_link on feeds(feed_link);
create table if not exists items ( create table if not exists items (
id string primary key, id integer primary key autoincrement,
guid string not null,
feed_id references feeds(id), feed_id references feeds(id),
title text, title text,
link 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_feed_id on items(feed_id);
create index if not exists idx_item_status on items(status); 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 { type Storage struct {

View File

@ -45,5 +45,10 @@
return api('delete', '/api/folders/' + id) return api('delete', '/api/folders/' + id)
}, },
}, },
items: {
update: function(id, data) {
return api('put', '/api/items/' + id, data)
}
}
} }
})() })()

View File

@ -57,6 +57,7 @@ var vm = new Vue({
this.itemSelectedDetails = this.itemsById[newVal] this.itemSelectedDetails = this.itemsById[newVal]
if (this.itemSelectedDetails.status == 'unread') { if (this.itemSelectedDetails.status == 'unread') {
this.itemSelectedDetails.status = 'read' 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') { } else if (item.status != 'starred') {
item.status = 'starred' item.status = 'starred'
} }
api.items.update(item.id, {status: item.status})
}, },
toggleItemRead: function(item) { toggleItemRead: function(item) {
if (item.status == 'unread') { if (item.status == 'unread') {
@ -157,6 +159,7 @@ var vm = new Vue({
} else if (item.status == 'read') { } else if (item.status == 'read') {
item.status = 'unread' item.status = 'unread'
} }
api.items.update(item.id, {status: item.status})
}, },
} }
}) })