Add flush history feature
This commit is contained in:
parent
238b9e4c85
commit
549a4277b0
15 changed files with 79 additions and 17 deletions
|
@ -9,6 +9,7 @@ Miniflux is a minimalist and opinionated feed reader:
|
||||||
- Works only with Postgresql
|
- Works only with Postgresql
|
||||||
- Doesn't use any ORM
|
- Doesn't use any ORM
|
||||||
- Doesn't use any complicated framework
|
- Doesn't use any complicated framework
|
||||||
|
- Use only modern vanilla Javascript (ES6 and fetch)
|
||||||
- The number of features is volountary limited
|
- The number of features is volountary limited
|
||||||
|
|
||||||
It's simple, fast, lightweight and super easy to install.
|
It's simple, fast, lightweight and super easy to install.
|
||||||
|
@ -29,7 +30,7 @@ TODO
|
||||||
- [ ] External integrations (Pinboard, Wallabag...)
|
- [ ] External integrations (Pinboard, Wallabag...)
|
||||||
- [ ] Gzip compression
|
- [ ] Gzip compression
|
||||||
- [ ] Integration tests
|
- [ ] Integration tests
|
||||||
- [ ] Flush history
|
- [X] Flush history
|
||||||
- [ ] OAuth2
|
- [ ] OAuth2
|
||||||
|
|
||||||
Credits
|
Credits
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-21 14:55:14.456403496 -0800 PST m=+0.037949400
|
// 2017-11-21 15:41:59.495654213 -0800 PST m=+0.041889871
|
||||||
|
|
||||||
package locale
|
package locale
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Entry statuses
|
||||||
const (
|
const (
|
||||||
EntryStatusUnread = "unread"
|
EntryStatusUnread = "unread"
|
||||||
EntryStatusRead = "read"
|
EntryStatusRead = "read"
|
||||||
|
@ -17,6 +18,7 @@ const (
|
||||||
DefaultSortingDirection = "desc"
|
DefaultSortingDirection = "desc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Entry represents a feed item in the system.
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
|
@ -33,8 +35,10 @@ type Entry struct {
|
||||||
Category *Category `json:"category,omitempty"`
|
Category *Category `json:"category,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Entries represents a list of entries.
|
||||||
type Entries []*Entry
|
type Entries []*Entry
|
||||||
|
|
||||||
|
// ValidateEntryStatus makes sure the entry status is valid.
|
||||||
func ValidateEntryStatus(status string) error {
|
func ValidateEntryStatus(status string) error {
|
||||||
switch status {
|
switch status {
|
||||||
case EntryStatusRead, EntryStatusUnread, EntryStatusRemoved:
|
case EntryStatusRead, EntryStatusUnread, EntryStatusRemoved:
|
||||||
|
@ -44,6 +48,7 @@ func ValidateEntryStatus(status string) error {
|
||||||
return fmt.Errorf(`Invalid entry status, valid status values are: "%s", "%s" and "%s"`, EntryStatusRead, EntryStatusUnread, EntryStatusRemoved)
|
return fmt.Errorf(`Invalid entry status, valid status values are: "%s", "%s" and "%s"`, EntryStatusRead, EntryStatusUnread, EntryStatusRemoved)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateEntryOrder makes sure the sorting order is valid.
|
||||||
func ValidateEntryOrder(order string) error {
|
func ValidateEntryOrder(order string) error {
|
||||||
switch order {
|
switch order {
|
||||||
case "id", "status", "published_at", "category_title", "category_id":
|
case "id", "status", "published_at", "category_title", "category_id":
|
||||||
|
@ -53,6 +58,7 @@ func ValidateEntryOrder(order string) error {
|
||||||
return fmt.Errorf(`Invalid entry order, valid order values are: "id", "status", "published_at", "category_title", "category_id"`)
|
return fmt.Errorf(`Invalid entry order, valid order values are: "id", "status", "published_at", "category_title", "category_id"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateDirection makes sure the sorting direction is valid.
|
||||||
func ValidateDirection(direction string) error {
|
func ValidateDirection(direction string) error {
|
||||||
switch direction {
|
switch direction {
|
||||||
case "asc", "desc":
|
case "asc", "desc":
|
||||||
|
@ -62,6 +68,7 @@ func ValidateDirection(direction string) error {
|
||||||
return fmt.Errorf(`Invalid direction, valid direction values are: "asc" or "desc"`)
|
return fmt.Errorf(`Invalid direction, valid direction values are: "asc" or "desc"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOppositeDirection returns the opposite sorting direction.
|
||||||
func GetOppositeDirection(direction string) string {
|
func GetOppositeDirection(direction string) string {
|
||||||
if direction == "asc" {
|
if direction == "asc" {
|
||||||
return "desc"
|
return "desc"
|
||||||
|
|
|
@ -54,7 +54,10 @@ func (j *JsonResponse) ServerError(err error) {
|
||||||
log.Println("[API:ServerError]", err)
|
log.Println("[API:ServerError]", err)
|
||||||
j.writer.WriteHeader(http.StatusInternalServerError)
|
j.writer.WriteHeader(http.StatusInternalServerError)
|
||||||
j.commonHeaders()
|
j.commonHeaders()
|
||||||
j.writer.Write(j.encodeError(err))
|
|
||||||
|
if err != nil {
|
||||||
|
j.writer.Write(j.encodeError(err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JsonResponse) Forbidden() {
|
func (j *JsonResponse) Forbidden() {
|
||||||
|
|
|
@ -81,6 +81,7 @@ func getRoutes(store *storage.Storage, feedHandler *feed.Handler) *mux.Router {
|
||||||
|
|
||||||
router.Handle("/unread/entry/{entryID}", uiHandler.Use(uiController.ShowUnreadEntry)).Name("unreadEntry").Methods("GET")
|
router.Handle("/unread/entry/{entryID}", uiHandler.Use(uiController.ShowUnreadEntry)).Name("unreadEntry").Methods("GET")
|
||||||
router.Handle("/history/entry/{entryID}", uiHandler.Use(uiController.ShowReadEntry)).Name("readEntry").Methods("GET")
|
router.Handle("/history/entry/{entryID}", uiHandler.Use(uiController.ShowReadEntry)).Name("readEntry").Methods("GET")
|
||||||
|
router.Handle("/history/flush", uiHandler.Use(uiController.FlushHistory)).Name("flushHistory").Methods("GET")
|
||||||
router.Handle("/feed/{feedID}/entry/{entryID}", uiHandler.Use(uiController.ShowFeedEntry)).Name("feedEntry").Methods("GET")
|
router.Handle("/feed/{feedID}/entry/{entryID}", uiHandler.Use(uiController.ShowFeedEntry)).Name("feedEntry").Methods("GET")
|
||||||
router.Handle("/category/{categoryID}/entry/{entryID}", uiHandler.Use(uiController.ShowCategoryEntry)).Name("categoryEntry").Methods("GET")
|
router.Handle("/category/{categoryID}/entry/{entryID}", uiHandler.Use(uiController.ShowCategoryEntry)).Name("categoryEntry").Methods("GET")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-21 14:55:14.42928305 -0800 PST m=+0.010828954
|
// 2017-11-21 15:41:59.461181295 -0800 PST m=+0.007416953
|
||||||
|
|
||||||
package static
|
package static
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-21 14:55:14.43289693 -0800 PST m=+0.014442834
|
// 2017-11-21 15:41:59.464123652 -0800 PST m=+0.010359310
|
||||||
|
|
||||||
package static
|
package static
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-21 14:55:14.43700259 -0800 PST m=+0.018548494
|
// 2017-11-21 15:41:59.4687788 -0800 PST m=+0.015014458
|
||||||
|
|
||||||
package static
|
package static
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-21 14:55:14.455330256 -0800 PST m=+0.036876160
|
// 2017-11-21 15:41:59.491806442 -0800 PST m=+0.038042100
|
||||||
|
|
||||||
package template
|
package template
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
{{ define "content"}}
|
{{ define "content"}}
|
||||||
<section class="page-header">
|
<section class="page-header">
|
||||||
<h1>{{ t "History" }} ({{ .total }})</h1>
|
<h1>{{ t "History" }} ({{ .total }})</h1>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route "flushHistory" }}">{{ t "Flush history" }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{{ if not .entries }}
|
{{ if not .entries }}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-21 14:55:14.438565193 -0800 PST m=+0.020111097
|
// 2017-11-21 15:41:59.472545112 -0800 PST m=+0.018780770
|
||||||
|
|
||||||
package template
|
package template
|
||||||
|
|
||||||
|
@ -649,6 +649,11 @@ var templateViewsMap = map[string]string{
|
||||||
{{ define "content"}}
|
{{ define "content"}}
|
||||||
<section class="page-header">
|
<section class="page-header">
|
||||||
<h1>{{ t "History" }} ({{ .total }})</h1>
|
<h1>{{ t "History" }} ({{ .total }})</h1>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route "flushHistory" }}">{{ t "Flush history" }}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{{ if not .entries }}
|
{{ if not .entries }}
|
||||||
|
@ -980,7 +985,7 @@ var templateViewsMapChecksums = map[string]string{
|
||||||
"entry": "32e605edd6d43773ac31329d247ebd81d38d974cd43689d91de79fffec7fe04b",
|
"entry": "32e605edd6d43773ac31329d247ebd81d38d974cd43689d91de79fffec7fe04b",
|
||||||
"feed_entries": "9aff923b6c7452dec1514feada7e0d2bbc1ec21c6f5e9f48b2de41d1b731ffe4",
|
"feed_entries": "9aff923b6c7452dec1514feada7e0d2bbc1ec21c6f5e9f48b2de41d1b731ffe4",
|
||||||
"feeds": "94e43404a4044490c065c888a49bebd3ff51b588b9fb47d03c2598003aa40dca",
|
"feeds": "94e43404a4044490c065c888a49bebd3ff51b588b9fb47d03c2598003aa40dca",
|
||||||
"history": "439000d0be8fd716f3b89860af4d721e05baef0c2ccd2325ba020c940d6aa847",
|
"history": "947603cbde888516e62925f5d08fb0b13d930623d3ee4c690dbc22612fdda75e",
|
||||||
"import": "73b5112e20bfd232bf73334544186ea419505936bc237d481517a8622901878f",
|
"import": "73b5112e20bfd232bf73334544186ea419505936bc237d481517a8622901878f",
|
||||||
"login": "568f2f69f248048f3e55e9bbc719077a74ae23fe18f237aa40e3de37e97b7a41",
|
"login": "568f2f69f248048f3e55e9bbc719077a74ae23fe18f237aa40e3de37e97b7a41",
|
||||||
"sessions": "5ac3793f0ee74d0807bab6a173a1aa6508e98add5c022fa54c8fdf5c6b4a0e75",
|
"sessions": "5ac3793f0ee74d0807bab6a173a1aa6508e98add5c022fa54c8fdf5c6b4a0e75",
|
||||||
|
|
|
@ -6,12 +6,14 @@ package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/miniflux/miniflux2/model"
|
"github.com/miniflux/miniflux2/model"
|
||||||
"github.com/miniflux/miniflux2/server/core"
|
"github.com/miniflux/miniflux2/server/core"
|
||||||
"github.com/miniflux/miniflux2/server/ui/payload"
|
"github.com/miniflux/miniflux2/server/ui/payload"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ShowFeedEntry shows a single feed entry in "feed" mode.
|
||||||
func (c *Controller) ShowFeedEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
func (c *Controller) ShowFeedEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
user := ctx.GetLoggedUser()
|
user := ctx.GetLoggedUser()
|
||||||
sortingDirection := model.DefaultSortingDirection
|
sortingDirection := model.DefaultSortingDirection
|
||||||
|
@ -102,6 +104,7 @@ func (c *Controller) ShowFeedEntry(ctx *core.Context, request *core.Request, res
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShowCategoryEntry shows a single feed entry in "category" mode.
|
||||||
func (c *Controller) ShowCategoryEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
func (c *Controller) ShowCategoryEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
user := ctx.GetLoggedUser()
|
user := ctx.GetLoggedUser()
|
||||||
sortingDirection := model.DefaultSortingDirection
|
sortingDirection := model.DefaultSortingDirection
|
||||||
|
@ -192,6 +195,7 @@ func (c *Controller) ShowCategoryEntry(ctx *core.Context, request *core.Request,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShowUnreadEntry shows a single feed entry in "unread" mode.
|
||||||
func (c *Controller) ShowUnreadEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
func (c *Controller) ShowUnreadEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
user := ctx.GetLoggedUser()
|
user := ctx.GetLoggedUser()
|
||||||
sortingDirection := model.DefaultSortingDirection
|
sortingDirection := model.DefaultSortingDirection
|
||||||
|
@ -275,6 +279,7 @@ func (c *Controller) ShowUnreadEntry(ctx *core.Context, request *core.Request, r
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShowReadEntry shows a single feed entry in "history" mode.
|
||||||
func (c *Controller) ShowReadEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
func (c *Controller) ShowReadEntry(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
user := ctx.GetLoggedUser()
|
user := ctx.GetLoggedUser()
|
||||||
sortingDirection := model.DefaultSortingDirection
|
sortingDirection := model.DefaultSortingDirection
|
||||||
|
@ -349,6 +354,7 @@ func (c *Controller) ShowReadEntry(ctx *core.Context, request *core.Request, res
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateEntriesStatus handles Ajax request to update a list of entries.
|
||||||
func (c *Controller) UpdateEntriesStatus(ctx *core.Context, request *core.Request, response *core.Response) {
|
func (c *Controller) UpdateEntriesStatus(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
user := ctx.GetLoggedUser()
|
user := ctx.GetLoggedUser()
|
||||||
|
|
||||||
|
@ -360,14 +366,14 @@ func (c *Controller) UpdateEntriesStatus(ctx *core.Context, request *core.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(entryIDs) == 0 {
|
if len(entryIDs) == 0 {
|
||||||
response.Html().BadRequest(errors.New("The list of entryID is empty"))
|
response.Json().BadRequest(errors.New("The list of entryID is empty"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.store.SetEntriesStatus(user.ID, entryIDs, status)
|
err = c.store.SetEntriesStatus(user.ID, entryIDs, status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
response.Html().ServerError(nil)
|
response.Json().ServerError(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/miniflux/miniflux2/server/core"
|
"github.com/miniflux/miniflux2/server/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ShowHistoryPage renders the page with all read entries.
|
||||||
func (c *Controller) ShowHistoryPage(ctx *core.Context, request *core.Request, response *core.Response) {
|
func (c *Controller) ShowHistoryPage(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
user := ctx.GetLoggedUser()
|
user := ctx.GetLoggedUser()
|
||||||
offset := request.GetQueryIntegerParam("offset", 0)
|
offset := request.GetQueryIntegerParam("offset", 0)
|
||||||
|
@ -45,3 +46,16 @@ func (c *Controller) ShowHistoryPage(ctx *core.Context, request *core.Request, r
|
||||||
"menu": "history",
|
"menu": "history",
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlushHistory changes all "read" items to "removed".
|
||||||
|
func (c *Controller) FlushHistory(ctx *core.Context, request *core.Request, response *core.Response) {
|
||||||
|
user := ctx.GetLoggedUser()
|
||||||
|
|
||||||
|
err := c.store.FlushHistory(user.ID)
|
||||||
|
if err != nil {
|
||||||
|
response.Html().ServerError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Redirect(ctx.GetRoute("history"))
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// 2017-11-21 14:55:14.420877594 -0800 PST m=+0.002423498
|
// 2017-11-21 15:41:59.457985225 -0800 PST m=+0.004220883
|
||||||
|
|
||||||
package sql
|
package sql
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,20 @@ package storage
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/miniflux/miniflux2/helper"
|
"github.com/miniflux/miniflux2/helper"
|
||||||
"github.com/miniflux/miniflux2/model"
|
"github.com/miniflux/miniflux2/model"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetEntryQueryBuilder returns a new EntryQueryBuilder
|
||||||
func (s *Storage) GetEntryQueryBuilder(userID int64, timezone string) *EntryQueryBuilder {
|
func (s *Storage) GetEntryQueryBuilder(userID int64, timezone string) *EntryQueryBuilder {
|
||||||
return NewEntryQueryBuilder(s, userID, timezone)
|
return NewEntryQueryBuilder(s, userID, timezone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateEntry add a new entry.
|
||||||
func (s *Storage) CreateEntry(entry *model.Entry) error {
|
func (s *Storage) CreateEntry(entry *model.Entry) error {
|
||||||
query := `
|
query := `
|
||||||
INSERT INTO entries
|
INSERT INTO entries
|
||||||
|
@ -55,6 +58,7 @@ func (s *Storage) CreateEntry(entry *model.Entry) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateEntry update an entry when a feed is refreshed.
|
||||||
func (s *Storage) UpdateEntry(entry *model.Entry) error {
|
func (s *Storage) UpdateEntry(entry *model.Entry) error {
|
||||||
query := `
|
query := `
|
||||||
UPDATE entries SET
|
UPDATE entries SET
|
||||||
|
@ -76,6 +80,7 @@ func (s *Storage) UpdateEntry(entry *model.Entry) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EntryExists checks if an entry already exists based on its hash when refreshing a feed.
|
||||||
func (s *Storage) EntryExists(entry *model.Entry) bool {
|
func (s *Storage) EntryExists(entry *model.Entry) bool {
|
||||||
var result int
|
var result int
|
||||||
query := `SELECT count(*) as c FROM entries WHERE user_id=$1 AND feed_id=$2 AND hash=$3`
|
query := `SELECT count(*) as c FROM entries WHERE user_id=$1 AND feed_id=$2 AND hash=$3`
|
||||||
|
@ -83,6 +88,7 @@ func (s *Storage) EntryExists(entry *model.Entry) bool {
|
||||||
return result >= 1
|
return result >= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateEntries update a list of entries while refreshing a feed.
|
||||||
func (s *Storage) UpdateEntries(userID, feedID int64, entries model.Entries) (err error) {
|
func (s *Storage) UpdateEntries(userID, feedID int64, entries model.Entries) (err error) {
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
entry.UserID = userID
|
entry.UserID = userID
|
||||||
|
@ -102,22 +108,36 @@ func (s *Storage) UpdateEntries(userID, feedID int64, entries model.Entries) (er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetEntriesStatus update the status of the given list of entries.
|
||||||
func (s *Storage) SetEntriesStatus(userID int64, entryIDs []int64, status string) error {
|
func (s *Storage) SetEntriesStatus(userID int64, entryIDs []int64, status string) error {
|
||||||
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:SetEntriesStatus] userID=%d, entryIDs=%v, status=%s", userID, entryIDs, status))
|
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:SetEntriesStatus] userID=%d, entryIDs=%v, status=%s", userID, entryIDs, status))
|
||||||
|
|
||||||
query := `UPDATE entries SET status=$1 WHERE user_id=$2 AND id=ANY($3)`
|
query := `UPDATE entries SET status=$1 WHERE user_id=$2 AND id=ANY($3)`
|
||||||
result, err := s.db.Exec(query, status, userID, pq.Array(entryIDs))
|
result, err := s.db.Exec(query, status, userID, pq.Array(entryIDs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to update entry status: %v", err)
|
return fmt.Errorf("unable to update entries status: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := result.RowsAffected()
|
count, err := result.RowsAffected()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to update this entry: %v", err)
|
return fmt.Errorf("unable to update these entries: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return errors.New("Nothing has been updated")
|
return errors.New("nothing has been updated")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlushHistory set all entries with the status "read" to "removed".
|
||||||
|
func (s *Storage) FlushHistory(userID int64) error {
|
||||||
|
defer helper.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:FlushHistory] userID=%d", userID))
|
||||||
|
|
||||||
|
query := `UPDATE entries SET status=$1 WHERE user_id=$2 AND status=$3`
|
||||||
|
_, err := s.db.Exec(query, model.EntryStatusRemoved, userID, model.EntryStatusRead)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to flush history: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in a new issue