mirror of
https://github.com/miniflux/v2.git
synced 2025-09-15 18:57:04 +00:00
Add option to change the number of entries per page (fixes #40)
This commit is contained in:
parent
e32fa059e5
commit
5f266319a3
35 changed files with 174 additions and 52 deletions
|
@ -29,7 +29,7 @@ func (h *handler) showStarredPage(w http.ResponseWriter, r *http.Request) {
|
|||
builder.WithOrder(model.DefaultSortingOrder)
|
||||
builder.WithDirection(user.EntryDirection)
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
|
@ -48,7 +48,7 @@ func (h *handler) showStarredPage(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
view.Set("total", count)
|
||||
view.Set("entries", entries)
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "starred"), count, offset))
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "starred"), count, offset, user.EntriesPerPage))
|
||||
view.Set("menu", "starred")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
|
||||
|
|
|
@ -41,7 +41,7 @@ func (h *handler) showCategoryEntriesPage(w http.ResponseWriter, r *http.Request
|
|||
builder.WithDirection(user.EntryDirection)
|
||||
builder.WithStatus(model.EntryStatusUnread)
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
|
@ -60,7 +60,7 @@ func (h *handler) showCategoryEntriesPage(w http.ResponseWriter, r *http.Request
|
|||
view.Set("category", category)
|
||||
view.Set("total", count)
|
||||
view.Set("entries", entries)
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "categoryEntries", "categoryID", category.ID), count, offset))
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "categoryEntries", "categoryID", category.ID), count, offset, user.EntriesPerPage))
|
||||
view.Set("menu", "categories")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
|
||||
|
|
|
@ -41,7 +41,7 @@ func (h *handler) showCategoryEntriesAllPage(w http.ResponseWriter, r *http.Requ
|
|||
builder.WithDirection(user.EntryDirection)
|
||||
builder.WithoutStatus(model.EntryStatusRemoved)
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
|
@ -60,7 +60,7 @@ func (h *handler) showCategoryEntriesAllPage(w http.ResponseWriter, r *http.Requ
|
|||
view.Set("category", category)
|
||||
view.Set("total", count)
|
||||
view.Set("entries", entries)
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "categoryEntriesAll", "categoryID", category.ID), count, offset))
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "categoryEntriesAll", "categoryID", category.ID), count, offset, user.EntriesPerPage))
|
||||
view.Set("menu", "categories")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
|
||||
|
|
|
@ -41,7 +41,7 @@ func (h *handler) showFeedEntriesPage(w http.ResponseWriter, r *http.Request) {
|
|||
builder.WithOrder(model.DefaultSortingOrder)
|
||||
builder.WithDirection(user.EntryDirection)
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
|
@ -60,7 +60,7 @@ func (h *handler) showFeedEntriesPage(w http.ResponseWriter, r *http.Request) {
|
|||
view.Set("feed", feed)
|
||||
view.Set("entries", entries)
|
||||
view.Set("total", count)
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "feedEntries", "feedID", feed.ID), count, offset))
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "feedEntries", "feedID", feed.ID), count, offset, user.EntriesPerPage))
|
||||
view.Set("menu", "feeds")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
|
||||
|
|
|
@ -41,7 +41,7 @@ func (h *handler) showFeedEntriesAllPage(w http.ResponseWriter, r *http.Request)
|
|||
builder.WithOrder(model.DefaultSortingOrder)
|
||||
builder.WithDirection(user.EntryDirection)
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
|
@ -60,7 +60,7 @@ func (h *handler) showFeedEntriesAllPage(w http.ResponseWriter, r *http.Request)
|
|||
view.Set("feed", feed)
|
||||
view.Set("entries", entries)
|
||||
view.Set("total", count)
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "feedEntriesAll", "feedID", feed.ID), count, offset))
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "feedEntriesAll", "feedID", feed.ID), count, offset, user.EntriesPerPage))
|
||||
view.Set("menu", "feeds")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
|
||||
|
|
|
@ -6,6 +6,7 @@ package form // import "miniflux.app/ui/form"
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"miniflux.app/errors"
|
||||
"miniflux.app/model"
|
||||
|
@ -20,6 +21,7 @@ type SettingsForm struct {
|
|||
Language string
|
||||
Timezone string
|
||||
EntryDirection string
|
||||
EntriesPerPage int
|
||||
KeyboardShortcuts bool
|
||||
CustomCSS string
|
||||
}
|
||||
|
@ -31,6 +33,7 @@ func (s *SettingsForm) Merge(user *model.User) *model.User {
|
|||
user.Language = s.Language
|
||||
user.Timezone = s.Timezone
|
||||
user.EntryDirection = s.EntryDirection
|
||||
user.EntriesPerPage = s.EntriesPerPage
|
||||
user.KeyboardShortcuts = s.KeyboardShortcuts
|
||||
user.Extra["custom_css"] = s.CustomCSS
|
||||
|
||||
|
@ -47,6 +50,10 @@ func (s *SettingsForm) Validate() error {
|
|||
return errors.NewLocalizedError("error.settings_mandatory_fields")
|
||||
}
|
||||
|
||||
if s.EntriesPerPage < 1 {
|
||||
return errors.NewLocalizedError("error.entries_per_page_invalid")
|
||||
}
|
||||
|
||||
if s.Confirmation == "" {
|
||||
// Firefox insists on auto-completing the password field.
|
||||
// If the confirmation field is blank, the user probably
|
||||
|
@ -67,6 +74,10 @@ func (s *SettingsForm) Validate() error {
|
|||
|
||||
// NewSettingsForm returns a new SettingsForm.
|
||||
func NewSettingsForm(r *http.Request) *SettingsForm {
|
||||
entriesPerPage, err := strconv.ParseInt(r.FormValue("entries_per_page"), 10, 64)
|
||||
if err != nil {
|
||||
entriesPerPage = 0
|
||||
}
|
||||
return &SettingsForm{
|
||||
Username: r.FormValue("username"),
|
||||
Password: r.FormValue("password"),
|
||||
|
@ -75,6 +86,7 @@ func NewSettingsForm(r *http.Request) *SettingsForm {
|
|||
Language: r.FormValue("language"),
|
||||
Timezone: r.FormValue("timezone"),
|
||||
EntryDirection: r.FormValue("entry_direction"),
|
||||
EntriesPerPage: int(entriesPerPage),
|
||||
KeyboardShortcuts: r.FormValue("keyboard_shortcuts") == "1",
|
||||
CustomCSS: r.FormValue("custom_css"),
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ func TestValid(t *testing.T) {
|
|||
Language: "en_US",
|
||||
Timezone: "UTC",
|
||||
EntryDirection: "asc",
|
||||
EntriesPerPage: 50,
|
||||
}
|
||||
|
||||
err := settings.Validate()
|
||||
|
@ -30,6 +31,7 @@ func TestConfirmationEmpty(t *testing.T) {
|
|||
Language: "en_US",
|
||||
Timezone: "UTC",
|
||||
EntryDirection: "asc",
|
||||
EntriesPerPage: 50,
|
||||
}
|
||||
|
||||
err := settings.Validate()
|
||||
|
@ -51,6 +53,25 @@ func TestConfirmationIncorrect(t *testing.T) {
|
|||
Language: "en_US",
|
||||
Timezone: "UTC",
|
||||
EntryDirection: "asc",
|
||||
EntriesPerPage: 50,
|
||||
}
|
||||
|
||||
err := settings.Validate()
|
||||
if err == nil {
|
||||
t.Error("Validate should return an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEntriesPerPageNotValid(t *testing.T) {
|
||||
settings := &SettingsForm{
|
||||
Username: "user",
|
||||
Password: "hunter2",
|
||||
Confirmation: "hunter2",
|
||||
Theme: "default",
|
||||
Language: "en_US",
|
||||
Timezone: "UTC",
|
||||
EntryDirection: "asc",
|
||||
EntriesPerPage: 0,
|
||||
}
|
||||
|
||||
err := settings.Validate()
|
||||
|
|
|
@ -28,7 +28,7 @@ func (h *handler) showHistoryPage(w http.ResponseWriter, r *http.Request) {
|
|||
builder.WithOrder("changed_at")
|
||||
builder.WithDirection("desc")
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
|
@ -46,7 +46,7 @@ func (h *handler) showHistoryPage(w http.ResponseWriter, r *http.Request) {
|
|||
view := view.New(h.tpl, r, sess)
|
||||
view.Set("entries", entries)
|
||||
view.Set("total", count)
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "history"), count, offset))
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "history"), count, offset, user.EntriesPerPage))
|
||||
view.Set("menu", "history")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", h.store.CountUnreadEntries(user.ID))
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
|
||||
package ui // import "miniflux.app/ui"
|
||||
|
||||
const (
|
||||
nbItemsPerPage = 100
|
||||
)
|
||||
|
||||
type pagination struct {
|
||||
Route string
|
||||
Total int
|
||||
|
@ -20,7 +16,7 @@ type pagination struct {
|
|||
SearchQuery string
|
||||
}
|
||||
|
||||
func getPagination(route string, total, offset int) pagination {
|
||||
func getPagination(route string, total, offset, nbItemsPerPage int) pagination {
|
||||
nextOffset := 0
|
||||
prevOffset := 0
|
||||
showNext := (total - offset) > nbItemsPerPage
|
||||
|
|
|
@ -28,7 +28,7 @@ func (h *handler) showSearchEntriesPage(w http.ResponseWriter, r *http.Request)
|
|||
builder.WithSearchQuery(searchQuery)
|
||||
builder.WithoutStatus(model.EntryStatusRemoved)
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
|
@ -44,7 +44,7 @@ func (h *handler) showSearchEntriesPage(w http.ResponseWriter, r *http.Request)
|
|||
|
||||
sess := session.New(h.store, request.SessionID(r))
|
||||
view := view.New(h.tpl, r, sess)
|
||||
pagination := getPagination(route.Path(h.router, "searchEntries"), count, offset)
|
||||
pagination := getPagination(route.Path(h.router, "searchEntries"), count, offset, user.EntriesPerPage)
|
||||
pagination.SearchQuery = searchQuery
|
||||
|
||||
view.Set("searchQuery", searchQuery)
|
||||
|
|
|
@ -32,6 +32,7 @@ func (h *handler) showSettingsPage(w http.ResponseWriter, r *http.Request) {
|
|||
Language: user.Language,
|
||||
Timezone: user.Timezone,
|
||||
EntryDirection: user.EntryDirection,
|
||||
EntriesPerPage: user.EntriesPerPage,
|
||||
KeyboardShortcuts: user.KeyboardShortcuts,
|
||||
CustomCSS: user.Extra["custom_css"],
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -353,7 +353,8 @@ select {
|
|||
input[type="search"],
|
||||
input[type="url"],
|
||||
input[type="password"],
|
||||
input[type="text"] {
|
||||
input[type="text"],
|
||||
input[type="number"] {
|
||||
color: var(--input-color);
|
||||
background: var(--input-background);
|
||||
border: var(--input-border);
|
||||
|
@ -369,13 +370,18 @@ input[type="text"] {
|
|||
input[type="search"]:focus,
|
||||
input[type="url"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="text"]:focus {
|
||||
input[type="text"]:focus,
|
||||
input[type="number"]:focus {
|
||||
color: var(--input-focus-color);
|
||||
border-color: var(--input-focus-border-color);
|
||||
outline: 0;
|
||||
box-shadow: var(--input-focus-box-shadow);
|
||||
}
|
||||
|
||||
#form-entries-per-page {
|
||||
max-width: 80px;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ func (h *handler) showUnreadPage(w http.ResponseWriter, r *http.Request) {
|
|||
builder.WithOrder(model.DefaultSortingOrder)
|
||||
builder.WithDirection(user.EntryDirection)
|
||||
builder.WithOffset(offset)
|
||||
builder.WithLimit(nbItemsPerPage)
|
||||
builder.WithLimit(user.EntriesPerPage)
|
||||
entries, err := builder.GetEntries()
|
||||
if err != nil {
|
||||
html.ServerError(w, r, err)
|
||||
|
@ -51,7 +51,7 @@ func (h *handler) showUnreadPage(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
view.Set("entries", entries)
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "unread"), countUnread, offset))
|
||||
view.Set("pagination", getPagination(route.Path(h.router, "unread"), countUnread, offset, user.EntriesPerPage))
|
||||
view.Set("menu", "unread")
|
||||
view.Set("user", user)
|
||||
view.Set("countUnread", countUnread)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue