Display list of feeds per category
This commit is contained in:
parent
15fe9c20df
commit
fad9ad2be4
22 changed files with 345 additions and 141 deletions
|
@ -76,6 +76,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Lesezeichen",
|
||||
"page.categories.title": "Kategorien",
|
||||
"page.categories.no_feed": "Kein Abonnement.",
|
||||
"page.categories.feeds": "Siehe Abonnements",
|
||||
"page.categories.feed_count": [
|
||||
"Es gibt %d Abonnement.",
|
||||
"Es gibt %d Abonnements."
|
||||
|
@ -175,6 +176,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "Es befindet sich kein Artikel in dieser Kategorie.",
|
||||
"alert.no_feed_entry": "Es existiert kein Artikel für dieses Abonnement.",
|
||||
"alert.no_feed": "Es sind keine Abonnements vorhanden.",
|
||||
"alert.no_feed_in_category": "Für diese Kategorie gibt es kein Abonnement.",
|
||||
"alert.no_history": "Es existiert zur Zeit kein Verlauf.",
|
||||
"alert.feed_error": "Es gibt ein Problem mit diesem Abonnement",
|
||||
"alert.no_search_result": "Es gibt kein Ergebnis für diese Suche.",
|
||||
|
@ -379,6 +381,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Starred",
|
||||
"page.categories.title": "Categories",
|
||||
"page.categories.no_feed": "No feed.",
|
||||
"page.categories.feeds": "See subscriptions",
|
||||
"page.categories.feed_count": [
|
||||
"There is %d feed.",
|
||||
"There are %d feeds."
|
||||
|
@ -478,6 +481,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "There are no articles in this category.",
|
||||
"alert.no_feed_entry": "There are no articles for this feed.",
|
||||
"alert.no_feed": "You don't have any subscriptions.",
|
||||
"alert.no_feed_in_category": "There is no subscription for this category.",
|
||||
"alert.no_history": "There is no history at the moment.",
|
||||
"alert.feed_error": "There is a problem with this feed",
|
||||
"alert.no_search_result": "There are no results for this search.",
|
||||
|
@ -662,6 +666,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Marcadores",
|
||||
"page.categories.title": "Categorias",
|
||||
"page.categories.no_feed": "No fuente.",
|
||||
"page.categories.feeds": "Ver suscripciones",
|
||||
"page.categories.feed_count": [
|
||||
"Hay %d fuente.",
|
||||
"Hay %d fuentes."
|
||||
|
@ -761,6 +766,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "No hay artículos en esta categoria.",
|
||||
"alert.no_feed_entry": "No hay artículos para esta fuente.",
|
||||
"alert.no_feed": "No tienes suscripciones.",
|
||||
"alert.no_feed_in_category": "No hay suscripción para esta categoría.",
|
||||
"alert.no_history": "No hay historial en este momento.",
|
||||
"alert.feed_error": "Hay un problema con esta fuente.",
|
||||
"alert.no_search_result": "No hay resultados para esta búsqueda.",
|
||||
|
@ -945,6 +951,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Favoris",
|
||||
"page.categories.title": "Catégories",
|
||||
"page.categories.no_feed": "Aucun abonnement.",
|
||||
"page.categories.feeds": "Voir les abonnements",
|
||||
"page.categories.feed_count": [
|
||||
"Il y a %d abonnement.",
|
||||
"Il y a %d abonnements."
|
||||
|
@ -1044,6 +1051,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "Il n'y a aucun article dans cette catégorie.",
|
||||
"alert.no_feed_entry": "Il n'y a aucun article pour cet abonnement.",
|
||||
"alert.no_feed": "Vous n'avez aucun abonnement.",
|
||||
"alert.no_feed_in_category": "Il n'y a pas d'abonnement pour cette catégorie.",
|
||||
"alert.no_history": "Il n'y a aucun historique pour le moment.",
|
||||
"alert.feed_error": "Il y a un problème avec cet abonnement",
|
||||
"alert.no_search_result": "Il n'y a aucun résultat pour cette recherche.",
|
||||
|
@ -1248,6 +1256,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Preferiti",
|
||||
"page.categories.title": "Categorie",
|
||||
"page.categories.no_feed": "Nessun feed.",
|
||||
"page.categories.feeds": "Vedi abbonamenti",
|
||||
"page.categories.feed_count": [
|
||||
"C'è %d feed.",
|
||||
"Ci sono %d feed."
|
||||
|
@ -1347,6 +1356,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "Questa categoria non contiene alcun articolo.",
|
||||
"alert.no_feed_entry": "Questo feed non contiene alcun articolo.",
|
||||
"alert.no_feed": "Nessun feed disponibile.",
|
||||
"alert.no_feed_in_category": "Non esiste un abbonamento per questa categoria.",
|
||||
"alert.no_history": "La tua cronologia al momento è vuota.",
|
||||
"alert.feed_error": "Sembra ci sia un problema con questo feed",
|
||||
"alert.no_search_result": "La ricerca non ha prodotto risultati.",
|
||||
|
@ -1531,6 +1541,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Favorieten",
|
||||
"page.categories.title": "Categorieën",
|
||||
"page.categories.no_feed": "Geen feeds.",
|
||||
"page.categories.feeds": "Zie abonnementen",
|
||||
"page.categories.feed_count": [
|
||||
"Er is %d feed.",
|
||||
"Er zijn %d feeds."
|
||||
|
@ -1630,6 +1641,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "Deze categorie bevat geen feeds.",
|
||||
"alert.no_feed_entry": "Er zijn geen artikelen in deze feed.",
|
||||
"alert.no_feed": "Je hebt nog geen feeds geabboneerd staan.",
|
||||
"alert.no_feed_in_category": "Er is geen abonnement voor deze categorie.",
|
||||
"alert.no_history": "Geschiedenis is op dit moment leeg.",
|
||||
"alert.feed_error": "Er is een probleem met deze feed",
|
||||
"alert.no_search_result": "Er is geen resultaat voor deze zoekopdracht.",
|
||||
|
@ -1832,6 +1844,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Oznaczone gwiazdką",
|
||||
"page.categories.title": "Kategorie",
|
||||
"page.categories.no_feed": "Brak kanałów.",
|
||||
"page.categories.feeds": "Zobacz subskrypcje",
|
||||
"page.categories.feed_count": [
|
||||
"Jest %d kanał.",
|
||||
"Są %d kanały.",
|
||||
|
@ -1933,6 +1946,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "W tej kategorii nie ma żadnych artykułów",
|
||||
"alert.no_feed_entry": "Nie ma artykułu dla tego kanału.",
|
||||
"alert.no_feed": "Nie masz żadnej subskrypcji.",
|
||||
"alert.no_feed_in_category": "Nie ma subskrypcji dla tej kategorii.",
|
||||
"alert.no_history": "Obecnie nie ma żadnej historii.",
|
||||
"alert.feed_error": "Z tym kanałem jest problem",
|
||||
"alert.no_search_result": "Brak wyników dla tego wyszukiwania.",
|
||||
|
@ -2141,6 +2155,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "Избранное",
|
||||
"page.categories.title": "Категории",
|
||||
"page.categories.no_feed": "Нет подписок.",
|
||||
"page.categories.feeds": "Посмотреть подписку",
|
||||
"page.categories.feed_count": [
|
||||
"Есть %d подписка.",
|
||||
"Есть %d подписки.",
|
||||
|
@ -2242,6 +2257,7 @@ var translations = map[string]string{
|
|||
"alert.no_category_entry": "В этой категории нет статей.",
|
||||
"alert.no_feed_entry": "В этой подписке отсутствуют статьи.",
|
||||
"alert.no_feed": "У вас нет ни одной подписки.",
|
||||
"alert.no_feed_in_category": "Для этой категории нет подписки.",
|
||||
"alert.no_history": "Истории пока нет.",
|
||||
"alert.feed_error": "С этой подпиской есть проблема",
|
||||
"alert.no_search_result": "Нет результатов для данного поискового запроса.",
|
||||
|
@ -2432,6 +2448,7 @@ var translations = map[string]string{
|
|||
"page.starred.title": "星标",
|
||||
"page.categories.title": "分类",
|
||||
"page.categories.no_feed": "没有源",
|
||||
"page.categories.feeds": "查看订阅",
|
||||
"page.categories.feed_count": [
|
||||
"有 %d 个源"
|
||||
],
|
||||
|
@ -2532,6 +2549,7 @@ var translations = map[string]string{
|
|||
"alert.no_history": "目前没有历史",
|
||||
"alert.feed_error": "该源存在问题",
|
||||
"alert.no_search_result": "该搜索没有结果",
|
||||
"alert.no_feed_in_category": "没有该类别的订阅。",
|
||||
"alert.no_unread_entry": "目前没有未读文章",
|
||||
"alert.no_user": "您是目前仅有的用户",
|
||||
"alert.account_unlinked": "您的外部帐户现已解除关联!",
|
||||
|
@ -2656,13 +2674,13 @@ var translations = map[string]string{
|
|||
}
|
||||
|
||||
var translationsChecksums = map[string]string{
|
||||
"de_DE": "ec2dd4be11e4bb29efaa6cd124a1edd2e5271889d31d7fda92781be014388387",
|
||||
"en_US": "8010481cea76d28aad37c00fb0f481514f81c1581a6172b4a4ad17ad61e2eee0",
|
||||
"es_ES": "be58c4452068277826022931d86bd561fe150250756a6254985de5aa6d8129b7",
|
||||
"fr_FR": "4d3fa6084994a7b3121dd9c1f3baf8c1b0e519f6012aeaa805e5132ec1eaa60e",
|
||||
"it_IT": "3246b020b7ea01f762f19c9ee2825605b0e42f6ffdd34fd6306193597650f8d7",
|
||||
"nl_NL": "c58d1100bcd345824086d0df255381f7789379d0e2b95e146be009ad82e0aa5f",
|
||||
"pl_PL": "b438c4119ed5685950293f5c3c629a940c6475ca243c53f65879dfca6fc8cdd6",
|
||||
"ru_RU": "5b42510b54c678563791010f4c1fad1a024fa7029d268667bbfde1e7a1f02d88",
|
||||
"zh_CN": "30f72b341911682877bb86b0e82e9127be833625502ae41e9530447bb2f27de3",
|
||||
"de_DE": "08618fb4a57b1d427ec627ac6c46958bbe16b262a588aa640ad5be8b5e15562d",
|
||||
"en_US": "a611f133d106bb896bbe15df036838f33b7c7848abbf15829e918233e91783eb",
|
||||
"es_ES": "f47862bcd9af07d96510c3c24f89f0718f1325cde375954babe73766c62a6eca",
|
||||
"fr_FR": "0aca382d06630935b905452960a8dceac6f062cd5ebe2967b3837006a282f171",
|
||||
"it_IT": "60716683ca6d6e311154900508c0f8c389664096f3ab41eb9dd745914d497034",
|
||||
"nl_NL": "516c91a2be0f0b5c09e0183d61e53bfce2c8f60b8a5cb06593f0170ad6043f99",
|
||||
"pl_PL": "1fcf9422514fc7ebac57355a50c37d146fad6d19b879ba0dad29c49dfb20e00a",
|
||||
"ru_RU": "e701297d7c1b456dda066877bc5c6d18c9523f96eff3b4d53d13c6e6bf8f84a6",
|
||||
"zh_CN": "4da796ef2fdaf1898d2a17be6668b8308daebc97185bf69a698809067856c6ce",
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Lesezeichen",
|
||||
"page.categories.title": "Kategorien",
|
||||
"page.categories.no_feed": "Kein Abonnement.",
|
||||
"page.categories.feeds": "Siehe Abonnements",
|
||||
"page.categories.feed_count": [
|
||||
"Es gibt %d Abonnement.",
|
||||
"Es gibt %d Abonnements."
|
||||
|
@ -170,6 +171,7 @@
|
|||
"alert.no_category_entry": "Es befindet sich kein Artikel in dieser Kategorie.",
|
||||
"alert.no_feed_entry": "Es existiert kein Artikel für dieses Abonnement.",
|
||||
"alert.no_feed": "Es sind keine Abonnements vorhanden.",
|
||||
"alert.no_feed_in_category": "Für diese Kategorie gibt es kein Abonnement.",
|
||||
"alert.no_history": "Es existiert zur Zeit kein Verlauf.",
|
||||
"alert.feed_error": "Es gibt ein Problem mit diesem Abonnement",
|
||||
"alert.no_search_result": "Es gibt kein Ergebnis für diese Suche.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Starred",
|
||||
"page.categories.title": "Categories",
|
||||
"page.categories.no_feed": "No feed.",
|
||||
"page.categories.feeds": "See subscriptions",
|
||||
"page.categories.feed_count": [
|
||||
"There is %d feed.",
|
||||
"There are %d feeds."
|
||||
|
@ -170,6 +171,7 @@
|
|||
"alert.no_category_entry": "There are no articles in this category.",
|
||||
"alert.no_feed_entry": "There are no articles for this feed.",
|
||||
"alert.no_feed": "You don't have any subscriptions.",
|
||||
"alert.no_feed_in_category": "There is no subscription for this category.",
|
||||
"alert.no_history": "There is no history at the moment.",
|
||||
"alert.feed_error": "There is a problem with this feed",
|
||||
"alert.no_search_result": "There are no results for this search.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Marcadores",
|
||||
"page.categories.title": "Categorias",
|
||||
"page.categories.no_feed": "No fuente.",
|
||||
"page.categories.feeds": "Ver suscripciones",
|
||||
"page.categories.feed_count": [
|
||||
"Hay %d fuente.",
|
||||
"Hay %d fuentes."
|
||||
|
@ -170,6 +171,7 @@
|
|||
"alert.no_category_entry": "No hay artículos en esta categoria.",
|
||||
"alert.no_feed_entry": "No hay artículos para esta fuente.",
|
||||
"alert.no_feed": "No tienes suscripciones.",
|
||||
"alert.no_feed_in_category": "No hay suscripción para esta categoría.",
|
||||
"alert.no_history": "No hay historial en este momento.",
|
||||
"alert.feed_error": "Hay un problema con esta fuente.",
|
||||
"alert.no_search_result": "No hay resultados para esta búsqueda.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Favoris",
|
||||
"page.categories.title": "Catégories",
|
||||
"page.categories.no_feed": "Aucun abonnement.",
|
||||
"page.categories.feeds": "Voir les abonnements",
|
||||
"page.categories.feed_count": [
|
||||
"Il y a %d abonnement.",
|
||||
"Il y a %d abonnements."
|
||||
|
@ -170,6 +171,7 @@
|
|||
"alert.no_category_entry": "Il n'y a aucun article dans cette catégorie.",
|
||||
"alert.no_feed_entry": "Il n'y a aucun article pour cet abonnement.",
|
||||
"alert.no_feed": "Vous n'avez aucun abonnement.",
|
||||
"alert.no_feed_in_category": "Il n'y a pas d'abonnement pour cette catégorie.",
|
||||
"alert.no_history": "Il n'y a aucun historique pour le moment.",
|
||||
"alert.feed_error": "Il y a un problème avec cet abonnement",
|
||||
"alert.no_search_result": "Il n'y a aucun résultat pour cette recherche.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Preferiti",
|
||||
"page.categories.title": "Categorie",
|
||||
"page.categories.no_feed": "Nessun feed.",
|
||||
"page.categories.feeds": "Vedi abbonamenti",
|
||||
"page.categories.feed_count": [
|
||||
"C'è %d feed.",
|
||||
"Ci sono %d feed."
|
||||
|
@ -170,6 +171,7 @@
|
|||
"alert.no_category_entry": "Questa categoria non contiene alcun articolo.",
|
||||
"alert.no_feed_entry": "Questo feed non contiene alcun articolo.",
|
||||
"alert.no_feed": "Nessun feed disponibile.",
|
||||
"alert.no_feed_in_category": "Non esiste un abbonamento per questa categoria.",
|
||||
"alert.no_history": "La tua cronologia al momento è vuota.",
|
||||
"alert.feed_error": "Sembra ci sia un problema con questo feed",
|
||||
"alert.no_search_result": "La ricerca non ha prodotto risultati.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Favorieten",
|
||||
"page.categories.title": "Categorieën",
|
||||
"page.categories.no_feed": "Geen feeds.",
|
||||
"page.categories.feeds": "Zie abonnementen",
|
||||
"page.categories.feed_count": [
|
||||
"Er is %d feed.",
|
||||
"Er zijn %d feeds."
|
||||
|
@ -170,6 +171,7 @@
|
|||
"alert.no_category_entry": "Deze categorie bevat geen feeds.",
|
||||
"alert.no_feed_entry": "Er zijn geen artikelen in deze feed.",
|
||||
"alert.no_feed": "Je hebt nog geen feeds geabboneerd staan.",
|
||||
"alert.no_feed_in_category": "Er is geen abonnement voor deze categorie.",
|
||||
"alert.no_history": "Geschiedenis is op dit moment leeg.",
|
||||
"alert.feed_error": "Er is een probleem met deze feed",
|
||||
"alert.no_search_result": "Er is geen resultaat voor deze zoekopdracht.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Oznaczone gwiazdką",
|
||||
"page.categories.title": "Kategorie",
|
||||
"page.categories.no_feed": "Brak kanałów.",
|
||||
"page.categories.feeds": "Zobacz subskrypcje",
|
||||
"page.categories.feed_count": [
|
||||
"Jest %d kanał.",
|
||||
"Są %d kanały.",
|
||||
|
@ -172,6 +173,7 @@
|
|||
"alert.no_category_entry": "W tej kategorii nie ma żadnych artykułów",
|
||||
"alert.no_feed_entry": "Nie ma artykułu dla tego kanału.",
|
||||
"alert.no_feed": "Nie masz żadnej subskrypcji.",
|
||||
"alert.no_feed_in_category": "Nie ma subskrypcji dla tej kategorii.",
|
||||
"alert.no_history": "Obecnie nie ma żadnej historii.",
|
||||
"alert.feed_error": "Z tym kanałem jest problem",
|
||||
"alert.no_search_result": "Brak wyników dla tego wyszukiwania.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "Избранное",
|
||||
"page.categories.title": "Категории",
|
||||
"page.categories.no_feed": "Нет подписок.",
|
||||
"page.categories.feeds": "Посмотреть подписку",
|
||||
"page.categories.feed_count": [
|
||||
"Есть %d подписка.",
|
||||
"Есть %d подписки.",
|
||||
|
@ -172,6 +173,7 @@
|
|||
"alert.no_category_entry": "В этой категории нет статей.",
|
||||
"alert.no_feed_entry": "В этой подписке отсутствуют статьи.",
|
||||
"alert.no_feed": "У вас нет ни одной подписки.",
|
||||
"alert.no_feed_in_category": "Для этой категории нет подписки.",
|
||||
"alert.no_history": "Истории пока нет.",
|
||||
"alert.feed_error": "С этой подпиской есть проблема",
|
||||
"alert.no_search_result": "Нет результатов для данного поискового запроса.",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"page.starred.title": "星标",
|
||||
"page.categories.title": "分类",
|
||||
"page.categories.no_feed": "没有源",
|
||||
"page.categories.feeds": "查看订阅",
|
||||
"page.categories.feed_count": [
|
||||
"有 %d 个源"
|
||||
],
|
||||
|
@ -171,6 +172,7 @@
|
|||
"alert.no_history": "目前没有历史",
|
||||
"alert.feed_error": "该源存在问题",
|
||||
"alert.no_search_result": "该搜索没有结果",
|
||||
"alert.no_feed_in_category": "没有该类别的订阅。",
|
||||
"alert.no_unread_entry": "目前没有未读文章",
|
||||
"alert.no_user": "您是目前仅有的用户",
|
||||
"alert.account_unlinked": "您的外部帐户现已解除关联!",
|
||||
|
|
|
@ -139,7 +139,6 @@ func (s *Storage) Feeds(userID int64) (model.Feeds, error) {
|
|||
|
||||
// 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,
|
||||
|
@ -166,7 +165,43 @@ func (s *Storage) FeedsWithCounters(userID int64) (model.Feeds, error) {
|
|||
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)
|
||||
return s.fetchFeedsWithCounters(query, userID)
|
||||
}
|
||||
|
||||
// FeedsByCategoryWithCounters returns all feeds of the given user/category with counters of read and unread entries.
|
||||
func (s *Storage) FeedsByCategoryWithCounters(userID, categoryID int64) (model.Feeds, error) {
|
||||
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 AND f.category_id=$2
|
||||
ORDER BY f.parsing_error_count DESC, unread_count DESC, lower(f.title) ASC
|
||||
`
|
||||
return s.fetchFeedsWithCounters(query, userID, categoryID)
|
||||
}
|
||||
|
||||
func (s *Storage) fetchFeedsWithCounters(query string, args ...interface{}) (model.Feeds, error) {
|
||||
feeds := make(model.Feeds, 0)
|
||||
rows, err := s.db.Query(query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`store: unable to fetch feeds: %v`, err)
|
||||
}
|
||||
|
@ -176,7 +211,7 @@ func (s *Storage) FeedsWithCounters(userID int64) (model.Feeds, error) {
|
|||
var feed model.Feed
|
||||
var iconID interface{}
|
||||
var tz string
|
||||
feed.Category = &model.Category{UserID: userID}
|
||||
feed.Category = &model.Category{}
|
||||
|
||||
err := rows.Scan(
|
||||
&feed.ID,
|
||||
|
@ -213,6 +248,7 @@ func (s *Storage) FeedsWithCounters(userID int64) (model.Feeds, error) {
|
|||
}
|
||||
|
||||
feed.CheckedAt = timezone.Convert(tz, feed.CheckedAt)
|
||||
feed.Category.UserID = feed.UserID
|
||||
feeds = append(feeds, &feed)
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,62 @@ var templateCommonMap = map[string]string{
|
|||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}`,
|
||||
"feed_list": `{{ define "feed_list" }}
|
||||
<div class="items">
|
||||
{{ range .feeds }}
|
||||
<article class="item {{ if ne .ParsingErrorCount 0 }}feed-parsing-error{{ end }}">
|
||||
<div class="item-header">
|
||||
<span class="item-title">
|
||||
{{ if .Icon }}
|
||||
<img src="{{ route "icon" "iconID" .Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Title }}">
|
||||
{{ end }}
|
||||
{{ if .Disabled }} 🚫 {{ end }}
|
||||
<a href="{{ route "feedEntries" "feedID" .ID }}">{{ .Title }}</a>
|
||||
</span>
|
||||
<span class="feed-entries-counter">
|
||||
(<span title="{{ t "page.feeds.unread_counter" }}">{{ .UnreadCount }}</span>/<span title="{{ t "page.feeds.read_counter" }}">{{ .ReadCount }}</span>)
|
||||
</span>
|
||||
<span class="category">
|
||||
<a href="{{ route "categoryEntries" "categoryID" .Category.ID }}">{{ .Category.Title }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-meta">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ .SiteURL }}" title="{{ .SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ domain .SiteURL }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ t "page.feeds.last_check" }} <time datetime="{{ isodate .CheckedAt }}" title="{{ isodate .CheckedAt }}">{{ elapsed $.user.Timezone .CheckedAt }}</time>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "refreshFeed" "feedID" .ID }}">{{ t "menu.refresh_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "editFeed" "feedID" .ID }}">{{ t "menu.edit_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"
|
||||
data-confirm="true"
|
||||
data-label-question="{{ t "confirm.question" }}"
|
||||
data-label-yes="{{ t "confirm.yes" }}"
|
||||
data-label-no="{{ t "confirm.no" }}"
|
||||
data-label-loading="{{ t "confirm.loading" }}"
|
||||
data-url="{{ route "removeFeed" "feedID" .ID }}">{{ t "action.remove" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{ if ne .ParsingErrorCount 0 }}
|
||||
<div class="parsing-error">
|
||||
<strong title="{{ .ParsingErrorMsg }}" class="parsing-error-count">{{ plural "page.feeds.error_count" .ParsingErrorCount .ParsingErrorCount }}</strong>
|
||||
- <small class="parsing-error-message">{{ .ParsingErrorMsg }}</small>
|
||||
</div>
|
||||
{{ end }}
|
||||
</article>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}`,
|
||||
"item_meta": `{{ define "item_meta" }}
|
||||
<div class="item-meta">
|
||||
|
@ -274,6 +330,7 @@ var templateCommonMap = map[string]string{
|
|||
|
||||
var templateCommonMapChecksums = map[string]string{
|
||||
"entry_pagination": "4faa91e2eae150c5e4eab4d258e039dfdd413bab7602f0009360e6d52898e353",
|
||||
"feed_list": "7b7ea2c7df07d048c83d86237d5b5e41bddce561273c652d9265950093ca261b",
|
||||
"item_meta": "34deb081a054f2948ad808bdb2c8603d6ab00c58f2f50c4ead0b47ae092888eb",
|
||||
"layout": "010e31c9dde88cb429b21f4b0c24bb3769043a3ef1ef4a57100314f5910c8725",
|
||||
"pagination": "3386e90c6e1230311459e9a484629bc5d5bf39514a75ef2e73bbbc61142f7abb",
|
||||
|
|
|
@ -20,18 +20,13 @@
|
|||
<span class="item-title">
|
||||
<a href="{{ route "categoryEntries" "categoryID" .ID }}">{{ .Title }}</a>
|
||||
</span>
|
||||
(<span title="{{ if eq .FeedCount 0 }}{{ t "page.categories.no_feed" }}{{ else }}{{ plural "page.categories.feed_count" .FeedCount .FeedCount }}{{ end }}">{{ .FeedCount }}</span>)
|
||||
</div>
|
||||
<div class="item-meta">
|
||||
<ul>
|
||||
<li>
|
||||
{{ if eq .FeedCount 0 }}
|
||||
{{ t "page.categories.no_feed" }}
|
||||
{{ else }}
|
||||
{{ plural "page.categories.feed_count" .FeedCount .FeedCount }}
|
||||
{{ end }}
|
||||
<a href="{{ route "categoryFeeds" "categoryID" .ID }}">{{ t "page.categories.feeds" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "editCategory" "categoryID" .ID }}">{{ t "menu.edit_category" }}</a>
|
||||
</li>
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
<a href="{{ route "categoryEntries" "categoryID" .category.ID }}">{{ t "menu.show_only_unread_entries" }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
<li>
|
||||
<a href="{{ route "categoryFeeds" "categoryID" .category.ID }}">{{ t "menu.feeds" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
|
34
template/html/category_feeds.html
Normal file
34
template/html/category_feeds.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
{{ define "title"}}{{ .category.Title }} > {{ t "page.feeds.title" }} ({{ .total }}){{ end }}
|
||||
|
||||
{{ define "content"}}
|
||||
<section class="page-header">
|
||||
<h1>{{ .category.Title }} > {{ t "page.feeds.title" }} ({{ .total }})</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "categories" }}">{{ t "menu.categories" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "editCategory" "categoryID" .category.ID }}">{{ t "menu.edit_category" }}</a>
|
||||
</li>
|
||||
{{ if eq .total 0 }}
|
||||
<li>
|
||||
<a href="#"
|
||||
data-confirm="true"
|
||||
data-label-question="{{ t "confirm.question" }}"
|
||||
data-label-yes="{{ t "confirm.yes" }}"
|
||||
data-label-no="{{ t "confirm.no" }}"
|
||||
data-label-loading="{{ t "confirm.loading" }}"
|
||||
data-redirect-url="{{ route "categories" }}"
|
||||
data-url="{{ route "removeCategory" "categoryID" .category.ID }}">{{ t "action.remove" }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{{ if not .feeds }}
|
||||
<p class="alert">{{ t "alert.no_feed_in_category" }}</p>
|
||||
{{ else }}
|
||||
{{ template "feed_list" dict "user" .user "feeds" .feeds "ParsingErrorCount" .ParsingErrorCount }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
56
template/html/common/feed_list.html
Normal file
56
template/html/common/feed_list.html
Normal file
|
@ -0,0 +1,56 @@
|
|||
{{ define "feed_list" }}
|
||||
<div class="items">
|
||||
{{ range .feeds }}
|
||||
<article class="item {{ if ne .ParsingErrorCount 0 }}feed-parsing-error{{ end }}">
|
||||
<div class="item-header">
|
||||
<span class="item-title">
|
||||
{{ if .Icon }}
|
||||
<img src="{{ route "icon" "iconID" .Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Title }}">
|
||||
{{ end }}
|
||||
{{ if .Disabled }} 🚫 {{ end }}
|
||||
<a href="{{ route "feedEntries" "feedID" .ID }}">{{ .Title }}</a>
|
||||
</span>
|
||||
<span class="feed-entries-counter">
|
||||
(<span title="{{ t "page.feeds.unread_counter" }}">{{ .UnreadCount }}</span>/<span title="{{ t "page.feeds.read_counter" }}">{{ .ReadCount }}</span>)
|
||||
</span>
|
||||
<span class="category">
|
||||
<a href="{{ route "categoryEntries" "categoryID" .Category.ID }}">{{ .Category.Title }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-meta">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ .SiteURL }}" title="{{ .SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ domain .SiteURL }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ t "page.feeds.last_check" }} <time datetime="{{ isodate .CheckedAt }}" title="{{ isodate .CheckedAt }}">{{ elapsed $.user.Timezone .CheckedAt }}</time>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "refreshFeed" "feedID" .ID }}">{{ t "menu.refresh_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "editFeed" "feedID" .ID }}">{{ t "menu.edit_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"
|
||||
data-confirm="true"
|
||||
data-label-question="{{ t "confirm.question" }}"
|
||||
data-label-yes="{{ t "confirm.yes" }}"
|
||||
data-label-no="{{ t "confirm.no" }}"
|
||||
data-label-loading="{{ t "confirm.loading" }}"
|
||||
data-url="{{ route "removeFeed" "feedID" .ID }}">{{ t "action.remove" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{ if ne .ParsingErrorCount 0 }}
|
||||
<div class="parsing-error">
|
||||
<strong title="{{ .ParsingErrorMsg }}" class="parsing-error-count">{{ plural "page.feeds.error_count" .ParsingErrorCount .ParsingErrorCount }}</strong>
|
||||
- <small class="parsing-error-message">{{ .ParsingErrorMsg }}</small>
|
||||
</div>
|
||||
{{ end }}
|
||||
</article>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
|
@ -7,6 +7,9 @@
|
|||
<li>
|
||||
<a href="{{ route "categories" }}">{{ t "menu.categories" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "categoryFeeds" "categoryID" .category.ID }}">{{ t "menu.feeds" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "createCategory" }}">{{ t "menu.create_category" }}</a>
|
||||
</li>
|
||||
|
@ -24,7 +27,7 @@
|
|||
<input type="text" name="title" id="form-title" value="{{ .form.Title }}" required autofocus>
|
||||
|
||||
<div class="buttons">
|
||||
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button> {{ t "action.or" }} <a href="{{ route "categories" }}">{{ t "action.cancel" }}</a>
|
||||
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
|
|
|
@ -22,60 +22,7 @@
|
|||
{{ if not .feeds }}
|
||||
<p class="alert">{{ t "alert.no_feed" }}</p>
|
||||
{{ else }}
|
||||
<div class="items">
|
||||
{{ range .feeds }}
|
||||
<article class="item {{ if ne .ParsingErrorCount 0 }}feed-parsing-error{{ end }}">
|
||||
<div class="item-header">
|
||||
<span class="item-title">
|
||||
{{ if .Icon }}
|
||||
<img src="{{ route "icon" "iconID" .Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Title }}">
|
||||
{{ end }}
|
||||
{{ if .Disabled }} 🚫 {{ end }}
|
||||
<a href="{{ route "feedEntries" "feedID" .ID }}">{{ .Title }}</a>
|
||||
</span>
|
||||
<span class="feed-entries-counter">
|
||||
(<span title="{{ t "page.feeds.unread_counter" }}">{{ .UnreadCount }}</span>/<span title="{{ t "page.feeds.read_counter" }}">{{ .ReadCount }}</span>)
|
||||
</span>
|
||||
<span class="category">
|
||||
<a href="{{ route "categoryEntries" "categoryID" .Category.ID }}">{{ .Category.Title }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-meta">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ .SiteURL }}" title="{{ .SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ domain .SiteURL }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ t "page.feeds.last_check" }} <time datetime="{{ isodate .CheckedAt }}" title="{{ isodate .CheckedAt }}">{{ elapsed $.user.Timezone .CheckedAt }}</time>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "refreshFeed" "feedID" .ID }}">{{ t "menu.refresh_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "editFeed" "feedID" .ID }}">{{ t "menu.edit_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"
|
||||
data-confirm="true"
|
||||
data-label-question="{{ t "confirm.question" }}"
|
||||
data-label-yes="{{ t "confirm.yes" }}"
|
||||
data-label-no="{{ t "confirm.no" }}"
|
||||
data-label-loading="{{ t "confirm.loading" }}"
|
||||
data-url="{{ route "removeFeed" "feedID" .ID }}">{{ t "action.remove" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{ if ne .ParsingErrorCount 0 }}
|
||||
<div class="parsing-error">
|
||||
<strong title="{{ .ParsingErrorMsg }}" class="parsing-error-count">{{ plural "page.feeds.error_count" .ParsingErrorCount .ParsingErrorCount }}</strong>
|
||||
- <small class="parsing-error-message">{{ .ParsingErrorMsg }}</small>
|
||||
</div>
|
||||
{{ end }}
|
||||
</article>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ template "feed_list" dict "user" .user "feeds" .feeds "ParsingErrorCount" .ParsingErrorCount }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
|
|
|
@ -151,18 +151,13 @@ var templateViewsMap = map[string]string{
|
|||
<span class="item-title">
|
||||
<a href="{{ route "categoryEntries" "categoryID" .ID }}">{{ .Title }}</a>
|
||||
</span>
|
||||
(<span title="{{ if eq .FeedCount 0 }}{{ t "page.categories.no_feed" }}{{ else }}{{ plural "page.categories.feed_count" .FeedCount .FeedCount }}{{ end }}">{{ .FeedCount }}</span>)
|
||||
</div>
|
||||
<div class="item-meta">
|
||||
<ul>
|
||||
<li>
|
||||
{{ if eq .FeedCount 0 }}
|
||||
{{ t "page.categories.no_feed" }}
|
||||
{{ else }}
|
||||
{{ plural "page.categories.feed_count" .FeedCount .FeedCount }}
|
||||
{{ end }}
|
||||
<a href="{{ route "categoryFeeds" "categoryID" .ID }}">{{ t "page.categories.feeds" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "editCategory" "categoryID" .ID }}">{{ t "menu.edit_category" }}</a>
|
||||
</li>
|
||||
|
@ -212,6 +207,9 @@ var templateViewsMap = map[string]string{
|
|||
<a href="{{ route "categoryEntries" "categoryID" .category.ID }}">{{ t "menu.show_only_unread_entries" }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
<li>
|
||||
<a href="{{ route "categoryFeeds" "categoryID" .category.ID }}">{{ t "menu.feeds" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
@ -252,6 +250,41 @@ var templateViewsMap = map[string]string{
|
|||
{{ template "pagination" .pagination }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
`,
|
||||
"category_feeds": `{{ define "title"}}{{ .category.Title }} > {{ t "page.feeds.title" }} ({{ .total }}){{ end }}
|
||||
|
||||
{{ define "content"}}
|
||||
<section class="page-header">
|
||||
<h1>{{ .category.Title }} > {{ t "page.feeds.title" }} ({{ .total }})</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "categories" }}">{{ t "menu.categories" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "editCategory" "categoryID" .category.ID }}">{{ t "menu.edit_category" }}</a>
|
||||
</li>
|
||||
{{ if eq .total 0 }}
|
||||
<li>
|
||||
<a href="#"
|
||||
data-confirm="true"
|
||||
data-label-question="{{ t "confirm.question" }}"
|
||||
data-label-yes="{{ t "confirm.yes" }}"
|
||||
data-label-no="{{ t "confirm.no" }}"
|
||||
data-label-loading="{{ t "confirm.loading" }}"
|
||||
data-redirect-url="{{ route "categories" }}"
|
||||
data-url="{{ route "removeCategory" "categoryID" .category.ID }}">{{ t "action.remove" }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{{ if not .feeds }}
|
||||
<p class="alert">{{ t "alert.no_feed_in_category" }}</p>
|
||||
{{ else }}
|
||||
{{ template "feed_list" dict "user" .user "feeds" .feeds "ParsingErrorCount" .ParsingErrorCount }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
`,
|
||||
"choose_subscription": `{{ define "title"}}{{ t "page.add_feed.title" }}{{ end }}
|
||||
|
@ -366,6 +399,9 @@ var templateViewsMap = map[string]string{
|
|||
<li>
|
||||
<a href="{{ route "categories" }}">{{ t "menu.categories" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "categoryFeeds" "categoryID" .category.ID }}">{{ t "menu.feeds" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "createCategory" }}">{{ t "menu.create_category" }}</a>
|
||||
</li>
|
||||
|
@ -383,7 +419,7 @@ var templateViewsMap = map[string]string{
|
|||
<input type="text" name="title" id="form-title" value="{{ .form.Title }}" required autofocus>
|
||||
|
||||
<div class="buttons">
|
||||
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button> {{ t "action.or" }} <a href="{{ route "categories" }}">{{ t "action.cancel" }}</a>
|
||||
<button type="submit" class="button button-primary" data-label-loading="{{ t "form.submit.saving" }}">{{ t "action.update" }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
|
@ -778,60 +814,7 @@ var templateViewsMap = map[string]string{
|
|||
{{ if not .feeds }}
|
||||
<p class="alert">{{ t "alert.no_feed" }}</p>
|
||||
{{ else }}
|
||||
<div class="items">
|
||||
{{ range .feeds }}
|
||||
<article class="item {{ if ne .ParsingErrorCount 0 }}feed-parsing-error{{ end }}">
|
||||
<div class="item-header">
|
||||
<span class="item-title">
|
||||
{{ if .Icon }}
|
||||
<img src="{{ route "icon" "iconID" .Icon.IconID }}" width="16" height="16" loading="lazy" alt="{{ .Title }}">
|
||||
{{ end }}
|
||||
{{ if .Disabled }} 🚫 {{ end }}
|
||||
<a href="{{ route "feedEntries" "feedID" .ID }}">{{ .Title }}</a>
|
||||
</span>
|
||||
<span class="feed-entries-counter">
|
||||
(<span title="{{ t "page.feeds.unread_counter" }}">{{ .UnreadCount }}</span>/<span title="{{ t "page.feeds.read_counter" }}">{{ .ReadCount }}</span>)
|
||||
</span>
|
||||
<span class="category">
|
||||
<a href="{{ route "categoryEntries" "categoryID" .Category.ID }}">{{ .Category.Title }}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-meta">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ .SiteURL }}" title="{{ .SiteURL }}" target="_blank" rel="noopener noreferrer" referrerpolicy="no-referrer" data-original-link="true">{{ domain .SiteURL }}</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ t "page.feeds.last_check" }} <time datetime="{{ isodate .CheckedAt }}" title="{{ isodate .CheckedAt }}">{{ elapsed $.user.Timezone .CheckedAt }}</time>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route "refreshFeed" "feedID" .ID }}">{{ t "menu.refresh_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route "editFeed" "feedID" .ID }}">{{ t "menu.edit_feed" }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"
|
||||
data-confirm="true"
|
||||
data-label-question="{{ t "confirm.question" }}"
|
||||
data-label-yes="{{ t "confirm.yes" }}"
|
||||
data-label-no="{{ t "confirm.no" }}"
|
||||
data-label-loading="{{ t "confirm.loading" }}"
|
||||
data-url="{{ route "removeFeed" "feedID" .ID }}">{{ t "action.remove" }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{ if ne .ParsingErrorCount 0 }}
|
||||
<div class="parsing-error">
|
||||
<strong title="{{ .ParsingErrorMsg }}" class="parsing-error-count">{{ plural "page.feeds.error_count" .ParsingErrorCount .ParsingErrorCount }}</strong>
|
||||
- <small class="parsing-error-message">{{ .ParsingErrorMsg }}</small>
|
||||
</div>
|
||||
{{ end }}
|
||||
</article>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ template "feed_list" dict "user" .user "feeds" .feeds "ParsingErrorCount" .ParsingErrorCount }}
|
||||
{{ end }}
|
||||
|
||||
{{ end }}
|
||||
|
@ -1362,17 +1345,18 @@ var templateViewsMapChecksums = map[string]string{
|
|||
"about": "4035658497363d7af7f79be83190404eb21ec633fe8ec636bdfc219d9fc78cfc",
|
||||
"add_subscription": "a0f1d2bc02b6adc83dbeae593f74d9b936102cd6dd73302cdbec2137cafdcdd9",
|
||||
"bookmark_entries": "65588da78665699dd3f287f68325e9777d511f1a57fee4131a5bb6d00bb68df8",
|
||||
"categories": "642ee3cddbd825ee6ab5a77caa0d371096b55de0f1bd4ae3055b8c8a70507d8d",
|
||||
"category_entries": "3ec30d2cb97f29514ff61898a4f23d2aa73a24b3468b6d410b1c2d18c8808927",
|
||||
"categories": "2c5dd0ed6355bd5acc393bbf6117d20458b5581aab82036008324f6bbbe2af75",
|
||||
"category_entries": "dee7b9cd60c6c46f01dd4289940679df31c1fce28ce4aa7249fa459023e1eeb4",
|
||||
"category_feeds": "527c2ffbc4fcec775071424ba1022ae003525dba53a28cc41f48fb7b30aa984b",
|
||||
"choose_subscription": "33c04843d7c1b608d034e605e52681822fc6d79bc6b900c04915dd9ebae584e2",
|
||||
"create_category": "6b22b5ce51abf4e225e23a79f81be09a7fb90acb265e93a8faf9446dff74018d",
|
||||
"create_user": "9b73a55233615e461d1f07d99ad1d4d3b54532588ab960097ba3e090c85aaf3a",
|
||||
"edit_category": "daf073d2944a180ce5aaeb80b597eb69597a50dff55a9a1d6cf7938b48d768cb",
|
||||
"edit_category": "b1c0b38f1b714c5d884edcd61e5b5295a5f1c8b71c469b35391e4dcc97cc6d36",
|
||||
"edit_feed": "34aa0d668b3ea1a1b5fa480c20cebeae729b37010af3bb915d2a9eed73d3b996",
|
||||
"edit_user": "c692db9de1a084c57b93e95a14b041d39bf489846cbb91fc982a62b72b77062a",
|
||||
"entry": "24aeba26ef9a51ce585ca5c4af090f1de7d7bfd7f1e3ff1b63af520e2afa76bd",
|
||||
"feed_entries": "9c70b82f55e4b311eff20be1641733612e3c1b406ce8010861e4c417d97b6dcc",
|
||||
"feeds": "f11ba1c45cf3966843ddc406d96e048fc8f2235428e10111a1660a141ea2c42f",
|
||||
"feeds": "fa06cd1e1e3fec79132386972c640a2fe91237f5dba572389d5f45be74545f25",
|
||||
"history_entries": "87e17d39de70eb3fdbc4000326283be610928758eae7924e4b08dcb446f3b6a9",
|
||||
"import": "5eb56cecaa4d369b9acc991a82be7617710c551089a2e99d34ce8b6e5c37df0a",
|
||||
"integrations": "6104ff6ff3ac3c1ae5e850c78250aab6e99e2342a337589f3848459fa333766a",
|
||||
|
|
52
ui/category_feeds.go
Normal file
52
ui/category_feeds.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2019 Frédéric Guillot. All rights reserved.
|
||||
// Use of this source code is governed by the Apache 2.0
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ui // import "miniflux.app/ui"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"miniflux.app/http/request"
|
||||
"miniflux.app/http/response/html"
|
||||
"miniflux.app/ui/session"
|
||||
"miniflux.app/ui/view"
|
||||
)
|
||||
|
||||
func (h *handler) showCategoryFeedsPage(w http.ResponseWriter, r *http.Request) {
|
||||
user, err := h.store.UserByID(request.UserID(r))
|
||||
if err != nil {
|
||||
html.ServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
categoryID := request.RouteInt64Param(r, "categoryID")
|
||||
category, err := h.store.Category(request.UserID(r), categoryID)
|
||||
if err != nil {
|
||||
html.ServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if category == nil {
|
||||
html.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
feeds, err := h.store.FeedsByCategoryWithCounters(user.ID, categoryID)
|
||||
if err != nil {
|
||||
html.ServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
sess := session.New(h.store, request.SessionID(r))
|
||||
view := view.New(h.tpl, r, sess)
|
||||
view.Set("category", category)
|
||||
view.Set("feeds", feeds)
|
||||
view.Set("total", len(feeds))
|
||||
view.Set("menu", "categories")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
|
||||
view.Set("countErrorFeeds", h.store.CountErrorFeeds(user.ID))
|
||||
|
||||
html.OK(w, r, view.Render("category_feeds"))
|
||||
}
|
|
@ -66,5 +66,5 @@ func (h *handler) updateCategory(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
html.Redirect(w, r, route.Path(h.router, "categories"))
|
||||
html.Redirect(w, r, route.Path(h.router, "categoryFeeds", "categoryID", categoryID))
|
||||
}
|
||||
|
|
1
ui/ui.go
1
ui/ui.go
|
@ -74,6 +74,7 @@ func Serve(router *mux.Router, store *storage.Storage, pool *worker.Pool, feedHa
|
|||
uiRouter.HandleFunc("/categories", handler.showCategoryListPage).Name("categories").Methods("GET")
|
||||
uiRouter.HandleFunc("/category/create", handler.showCreateCategoryPage).Name("createCategory").Methods("GET")
|
||||
uiRouter.HandleFunc("/category/save", handler.saveCategory).Name("saveCategory").Methods("POST")
|
||||
uiRouter.HandleFunc("/category/{categoryID}/feeds", handler.showCategoryFeedsPage).Name("categoryFeeds").Methods("GET")
|
||||
uiRouter.HandleFunc("/category/{categoryID}/entries", handler.showCategoryEntriesPage).Name("categoryEntries").Methods("GET")
|
||||
uiRouter.HandleFunc("/category/{categoryID}/entries/all", handler.showCategoryEntriesAllPage).Name("categoryEntriesAll").Methods("GET")
|
||||
uiRouter.HandleFunc("/category/{categoryID}/edit", handler.showEditCategoryPage).Name("editCategory").Methods("GET")
|
||||
|
|
Loading…
Reference in a new issue