diff options
author | Maxim Baz <github@maximbaz.com> | 2019-10-30 05:44:35 +0100 |
---|---|---|
committer | Frédéric Guillot <fred@miniflux.net> | 2019-10-29 21:44:35 -0700 |
commit | e38333e272b24b6fcfa5399aa944f771558eb7aa (patch) | |
tree | 2ce26220cebdcafc01ba89fb59fa5a09da1268e7 | |
parent | 2eb2441f2ba9fcb50d17d8f7deead756187b3586 (diff) |
Show unread counters on feeds page
-rw-r--r-- | locale/translations.go | 27 | ||||
-rw-r--r-- | locale/translations/de_DE.json | 1 | ||||
-rw-r--r-- | locale/translations/en_US.json | 1 | ||||
-rw-r--r-- | locale/translations/es_ES.json | 1 | ||||
-rw-r--r-- | locale/translations/fr_FR.json | 1 | ||||
-rw-r--r-- | locale/translations/it_IT.json | 1 | ||||
-rw-r--r-- | locale/translations/nl_NL.json | 1 | ||||
-rw-r--r-- | locale/translations/pl_PL.json | 1 | ||||
-rw-r--r-- | locale/translations/ru_RU.json | 1 | ||||
-rw-r--r-- | locale/translations/zh_CN.json | 1 | ||||
-rw-r--r-- | model/feed.go | 2 | ||||
-rw-r--r-- | storage/feed.go | 74 | ||||
-rw-r--r-- | template/html/feeds.html | 5 | ||||
-rw-r--r-- | template/views.go | 7 | ||||
-rw-r--r-- | ui/feed_list.go | 2 |
15 files changed, 115 insertions, 11 deletions
diff --git a/locale/translations.go b/locale/translations.go index 8451de3..49bee8a 100644 --- a/locale/translations.go +++ b/locale/translations.go @@ -86,6 +86,7 @@ var translations = map[string]string{ "page.edit_user.title": "Benutzer bearbeiten: %s", "page.feeds.title": "Abonnements", "page.feeds.last_check": "Letzte Aktualisierung:", + "page.feeds.unread": "Ungelesen:", "page.feeds.error_count": [ "%d Fehler", "%d Fehler" @@ -387,6 +388,7 @@ var translations = map[string]string{ "page.edit_user.title": "Edit User: %s", "page.feeds.title": "Feeds", "page.feeds.last_check": "Last check:", + "page.feeds.unread": "Unread:", "page.feeds.error_count": [ "%d error", "%d errors" @@ -668,6 +670,7 @@ var translations = map[string]string{ "page.edit_user.title": "Editar usuario: %s", "page.feeds.title": "Fuentes", "page.feeds.last_check": "Última verificación:", + "page.feeds.unread": "No leídos:", "page.feeds.error_count": [ "%d error", "%d errores" @@ -949,6 +952,7 @@ var translations = map[string]string{ "page.edit_user.title": "Modification de l'utilisateur : %s", "page.feeds.title": "Abonnements", "page.feeds.last_check": "Dernière vérification :", + "page.feeds.unread": "Non lus:", "page.feeds.error_count": [ "%d erreur", "%d erreurs" @@ -1250,6 +1254,7 @@ var translations = map[string]string{ "page.edit_user.title": "Modifica utente: %s", "page.feeds.title": "Feed", "page.feeds.last_check": "Ultimo controllo:", + "page.feeds.unread": "Da leggere:", "page.feeds.error_count": [ "%d errore", "%d errori" @@ -1531,6 +1536,7 @@ var translations = map[string]string{ "page.edit_user.title": "Bewerk gebruiker: %s", "page.feeds.title": "Feeds", "page.feeds.last_check": "Laatste update:", + "page.feeds.unread": "Ongelezen:", "page.feeds.error_count": [ "%d error", "%d errors" @@ -1831,6 +1837,7 @@ var translations = map[string]string{ "page.edit_user.title": "Edytuj użytkownika: %s", "page.feeds.title": "Kanały", "page.feeds.last_check": "Ostatnia aktualizacja:", + "page.feeds.unread": "Nieprzeczytane:", "page.feeds.error_count": [ "%d błąd", "%d błąd", @@ -2138,6 +2145,7 @@ var translations = map[string]string{ "page.edit_user.title": "Изменить пользователя: %s", "page.feeds.title": "Подписки", "page.feeds.last_check": "Последняя проверка:", + "page.feeds.unread": "Непрочитано:", "page.feeds.error_count": [ "%d ошибка", "%d ошибки", @@ -2425,6 +2433,7 @@ var translations = map[string]string{ "page.edit_user.title": "编辑用户 : %s", "page.feeds.title": "源", "page.feeds.last_check": "最后检查时间:", + "page.feeds.unread": "未读:", "page.feeds.error_count": [ "%d 错误" ], @@ -2638,13 +2647,13 @@ var translations = map[string]string{ } var translationsChecksums = map[string]string{ - "de_DE": "52c82c151a27455501e54a4ea20339c965f030d7204ae9f55bf2639ef396b015", - "en_US": "ef73c3934c5df6c2346f96a4eb4b308f84404c58029aac2ee6859bc205ecb6b3", - "es_ES": "567fad5046d07efd69b9d29a3e8fa05503f935c02624c71851d9b1b3a8fa82d5", - "fr_FR": "11a3f01603a73b4a0c2921aea592bdb24086286f4f1343df4adaeb4a1471c1b9", - "it_IT": "19b9614980ded9ee4a5eea1f6623a8d2d4b763ffe81eae633d8c768bb58d6aea", - "nl_NL": "a91e2195ac0731a3788405a51c4201e1a89dcce35ef792356e8c17adb57aee97", - "pl_PL": "097bc9beac12f33d3a5e5ee98ccba0875e4d1c1bf13e38251a66ac450834c5b3", - "ru_RU": "b253bf709a2f4bcac2f894bd1797247481fa7c6b70a0a0d8785d8680be83bac8", - "zh_CN": "5004e07fa535ea56e7fbe1501bb8ff4191d1d214e51b4590110b660994c39f0d", + "de_DE": "c743f9eeca5d486c7b788e6ab20cf9f859e6c2138563d09599220fe40b3e25b5", + "en_US": "7992fd4e6fafceccbcf0b0972f0c085ad9a0eb7507de60eac407882c1f6457f5", + "es_ES": "e97765769afac01f4fd4cf868fa75657bd4d4e63999d9145a42d4de4248a9b2a", + "fr_FR": "50146f82d9b8e9ab69a5b3950827f7db47ba590ef074cf7f78b18f7e26fb0074", + "it_IT": "6a9f44c98b0dc8ab34306868bb9f93c4e511579a45c1fa8a48d637e10b2feca6", + "nl_NL": "afa731bd75e18b9483e9c6842b647f9d85405994ceca42f24b314bc967680606", + "pl_PL": "40aa0998688fb8dc1a308cda35bcea04be16c852944088c844c676c601a90bbd", + "ru_RU": "a1c72bb9ab48cf1b4fb47bfed081df75e391bb8d5c8b70036c1bdd38c57b6cb3", + "zh_CN": "a349de59436db0dc07172de89a481d95a660af206b13ae0de236a0cb8e31014b", } diff --git a/locale/translations/de_DE.json b/locale/translations/de_DE.json index be7e7ee..42adabe 100644 --- a/locale/translations/de_DE.json +++ b/locale/translations/de_DE.json @@ -81,6 +81,7 @@ "page.edit_user.title": "Benutzer bearbeiten: %s", "page.feeds.title": "Abonnements", "page.feeds.last_check": "Letzte Aktualisierung:", + "page.feeds.unread": "Ungelesen:", "page.feeds.error_count": [ "%d Fehler", "%d Fehler" diff --git a/locale/translations/en_US.json b/locale/translations/en_US.json index 9b31ed2..576c144 100644 --- a/locale/translations/en_US.json +++ b/locale/translations/en_US.json @@ -81,6 +81,7 @@ "page.edit_user.title": "Edit User: %s", "page.feeds.title": "Feeds", "page.feeds.last_check": "Last check:", + "page.feeds.unread": "Unread:", "page.feeds.error_count": [ "%d error", "%d errors" diff --git a/locale/translations/es_ES.json b/locale/translations/es_ES.json index 70337a4..a1973d6 100644 --- a/locale/translations/es_ES.json +++ b/locale/translations/es_ES.json @@ -81,6 +81,7 @@ "page.edit_user.title": "Editar usuario: %s", "page.feeds.title": "Fuentes", "page.feeds.last_check": "Última verificación:", + "page.feeds.unread": "No leídos:", "page.feeds.error_count": [ "%d error", "%d errores" diff --git a/locale/translations/fr_FR.json b/locale/translations/fr_FR.json index 26f35e5..04fdc6f 100644 --- a/locale/translations/fr_FR.json +++ b/locale/translations/fr_FR.json @@ -81,6 +81,7 @@ "page.edit_user.title": "Modification de l'utilisateur : %s", "page.feeds.title": "Abonnements", "page.feeds.last_check": "Dernière vérification :", + "page.feeds.unread": "Non lus:", "page.feeds.error_count": [ "%d erreur", "%d erreurs" diff --git a/locale/translations/it_IT.json b/locale/translations/it_IT.json index c8c0a43..86d2d94 100644 --- a/locale/translations/it_IT.json +++ b/locale/translations/it_IT.json @@ -81,6 +81,7 @@ "page.edit_user.title": "Modifica utente: %s", "page.feeds.title": "Feed", "page.feeds.last_check": "Ultimo controllo:", + "page.feeds.unread": "Da leggere:", "page.feeds.error_count": [ "%d errore", "%d errori" diff --git a/locale/translations/nl_NL.json b/locale/translations/nl_NL.json index 271fffc..ca82e2e 100644 --- a/locale/translations/nl_NL.json +++ b/locale/translations/nl_NL.json @@ -81,6 +81,7 @@ "page.edit_user.title": "Bewerk gebruiker: %s", "page.feeds.title": "Feeds", "page.feeds.last_check": "Laatste update:", + "page.feeds.unread": "Ongelezen:", "page.feeds.error_count": [ "%d error", "%d errors" diff --git a/locale/translations/pl_PL.json b/locale/translations/pl_PL.json index f4b7ec7..fc3bc3d 100644 --- a/locale/translations/pl_PL.json +++ b/locale/translations/pl_PL.json @@ -82,6 +82,7 @@ "page.edit_user.title": "Edytuj użytkownika: %s", "page.feeds.title": "Kanały", "page.feeds.last_check": "Ostatnia aktualizacja:", + "page.feeds.unread": "Nieprzeczytane:", "page.feeds.error_count": [ "%d błąd", "%d błąd", diff --git a/locale/translations/ru_RU.json b/locale/translations/ru_RU.json index 1e1fa89..ae5a68a 100644 --- a/locale/translations/ru_RU.json +++ b/locale/translations/ru_RU.json @@ -82,6 +82,7 @@ "page.edit_user.title": "Изменить пользователя: %s", "page.feeds.title": "Подписки", "page.feeds.last_check": "Последняя проверка:", + "page.feeds.unread": "Непрочитано:", "page.feeds.error_count": [ "%d ошибка", "%d ошибки", diff --git a/locale/translations/zh_CN.json b/locale/translations/zh_CN.json index a690187..99c74b5 100644 --- a/locale/translations/zh_CN.json +++ b/locale/translations/zh_CN.json @@ -80,6 +80,7 @@ "page.edit_user.title": "编辑用户 : %s", "page.feeds.title": "源", "page.feeds.last_check": "最后检查时间:", + "page.feeds.unread": "未读:", "page.feeds.error_count": [ "%d 错误" ], diff --git a/model/feed.go b/model/feed.go index 4b67cb1..0e25d7b 100644 --- a/model/feed.go +++ b/model/feed.go @@ -33,6 +33,8 @@ type Feed struct { Category *Category `json:"category,omitempty"` Entries Entries `json:"entries,omitempty"` Icon *FeedIcon `json:"icon"` + UnreadCount int `json:"unread_count"` + ReadCount int `json:"read_count"` } func (f *Feed) String() string { diff --git a/storage/feed.go b/storage/feed.go index 5b98b82..45ca9be 100644 --- a/storage/feed.go +++ b/storage/feed.go @@ -121,6 +121,80 @@ func (s *Storage) Feeds(userID int64) (model.Feeds, error) { return feeds, nil } +// FeedsWithCounters returns all feeds of the given user with counters of read and unread entries. +func (s *Storage) FeedsWithCounters(userID int64) (model.Feeds, error) { + feeds := make(model.Feeds, 0) + query := `SELECT + f.id, f.feed_url, f.site_url, f.title, f.etag_header, f.last_modified_header, + f.user_id, f.checked_at at time zone u.timezone, + f.parsing_error_count, f.parsing_error_msg, + f.scraper_rules, f.rewrite_rules, f.crawler, f.user_agent, + f.username, f.password, f.disabled, + f.category_id, c.title as category_title, + fi.icon_id, + u.timezone, + (SELECT count(*) FROM entries WHERE entries.feed_id=f.id AND status='unread') as unread_count, + (SELECT count(*) FROM entries WHERE entries.feed_id=f.id AND status='read') as read_count + FROM feeds f + LEFT JOIN categories c ON c.id=f.category_id + LEFT JOIN feed_icons fi ON fi.feed_id=f.id + LEFT JOIN users u ON u.id=f.user_id + WHERE f.user_id=$1 + ORDER BY f.parsing_error_count DESC, unread_count DESC, lower(f.title) ASC` + + rows, err := s.db.Query(query, userID) + if err != nil { + return nil, fmt.Errorf("unable to fetch feeds: %v", err) + } + defer rows.Close() + + for rows.Next() { + var feed model.Feed + var iconID interface{} + var tz string + feed.Category = &model.Category{UserID: userID} + + err := rows.Scan( + &feed.ID, + &feed.FeedURL, + &feed.SiteURL, + &feed.Title, + &feed.EtagHeader, + &feed.LastModifiedHeader, + &feed.UserID, + &feed.CheckedAt, + &feed.ParsingErrorCount, + &feed.ParsingErrorMsg, + &feed.ScraperRules, + &feed.RewriteRules, + &feed.Crawler, + &feed.UserAgent, + &feed.Username, + &feed.Password, + &feed.Disabled, + &feed.Category.ID, + &feed.Category.Title, + &iconID, + &tz, + &feed.UnreadCount, + &feed.ReadCount, + ) + + if err != nil { + return nil, fmt.Errorf("unable to fetch feeds row: %v", err) + } + + if iconID != nil { + feed.Icon = &model.FeedIcon{FeedID: feed.ID, IconID: iconID.(int64)} + } + + feed.CheckedAt = timezone.Convert(tz, feed.CheckedAt) + feeds = append(feeds, &feed) + } + + return feeds, nil +} + // FeedByID returns a feed by the ID. func (s *Storage) FeedByID(userID, feedID int64) (*model.Feed, error) { var feed model.Feed diff --git a/template/html/feeds.html b/template/html/feeds.html index e4a3231..f676f23 100644 --- a/template/html/feeds.html +++ b/template/html/feeds.html @@ -45,6 +45,11 @@ <li> {{ t "page.feeds.last_check" }} <time datetime="{{ isodate .CheckedAt }}" title="{{ isodate .CheckedAt }}">{{ elapsed $.user.Timezone .CheckedAt }}</time> </li> + {{ if gt .UnreadCount 0 }} + <li> + {{ t "page.feeds.unread" }} <span class="unread-counter">{{ .UnreadCount }}</span> + </li> + {{ end }} </ul> <ul> <li> diff --git a/template/views.go b/template/views.go index c951f8a..41adbc6 100644 --- a/template/views.go +++ b/template/views.go @@ -851,6 +851,11 @@ var templateViewsMap = map[string]string{ <li> {{ t "page.feeds.last_check" }} <time datetime="{{ isodate .CheckedAt }}" title="{{ isodate .CheckedAt }}">{{ elapsed $.user.Timezone .CheckedAt }}</time> </li> + {{ if gt .UnreadCount 0 }} + <li> + {{ t "page.feeds.unread" }} <span class="unread-counter">{{ .UnreadCount }}</span> + </li> + {{ end }} </ul> <ul> <li> @@ -1483,7 +1488,7 @@ var templateViewsMapChecksums = map[string]string{ "edit_user": "f4f99412ba771cfca2a2a42778b023b413c5494e9a287053ba8cf380c2865c5f", "entry": "24aeba26ef9a51ce585ca5c4af090f1de7d7bfd7f1e3ff1b63af520e2afa76bd", "feed_entries": "9c70b82f55e4b311eff20be1641733612e3c1b406ce8010861e4c417d97b6dcc", - "feeds": "fa2dad422445eca898c1daa4ab742691207a8c0d3c274eed84462bc610d22219", + "feeds": "55317035a4c008a720294c1858e9dc626f19e222ae41498db67dbb537ba7a456", "history_entries": "87e17d39de70eb3fdbc4000326283be610928758eae7924e4b08dcb446f3b6a9", "import": "5eb56cecaa4d369b9acc991a82be7617710c551089a2e99d34ce8b6e5c37df0a", "integrations": "f85b4a48ab1fc13b8ca94bfbbc44bd5e8784f35b26a63ec32cbe82b96b45e008", diff --git a/ui/feed_list.go b/ui/feed_list.go index 0c2c546..7c7b922 100644 --- a/ui/feed_list.go +++ b/ui/feed_list.go @@ -20,7 +20,7 @@ func (h *handler) showFeedsPage(w http.ResponseWriter, r *http.Request) { return } - feeds, err := h.store.Feeds(user.ID) + feeds, err := h.store.FeedsWithCounters(user.ID) if err != nil { html.ServerError(w, r, err) return |