From 10f5ceee35c234ee638f4bfd3b1d4ea790041a3e Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 6 Dec 2025 23:10:54 +0000 Subject: [PATCH] List page settings: Review of #5606 Updated setting display to show mulitple number inputs under one heading group. Updated settings to use general number field form view template. Updated translations to match display changes, and to advise on counts. Added page count control for search results. Added setting service method, to get settings as integers, with min/max/default control. Updating sorting group to be names "Lists & Sorting". Added tests to cover. --- app/App/HomeController.php | 4 +- app/Entities/Controllers/BookController.php | 2 +- .../Controllers/BookshelfController.php | 2 +- app/Search/SearchController.php | 5 +- app/Settings/AppSettingsStore.php | 6 +- app/Settings/SettingService.php | 15 ++++ lang/en/settings.php | 10 +-- resources/sass/_forms.scss | 4 + resources/views/form/number.blade.php | 3 +- .../settings/categories/sorting.blade.php | 57 ++++++------- tests/Settings/PageListLimitsTest.php | 81 +++++++++++++++++++ 11 files changed, 139 insertions(+), 50 deletions(-) create mode 100644 tests/Settings/PageListLimitsTest.php diff --git a/app/App/HomeController.php b/app/App/HomeController.php index 7ec8b0af2..00e2db3df 100644 --- a/app/App/HomeController.php +++ b/app/App/HomeController.php @@ -83,7 +83,7 @@ class HomeController extends Controller if ($homepageOption === 'bookshelves') { $shelves = $this->queries->shelves->visibleForListWithCover() ->orderBy($commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder()) - ->paginate(intval(setting('sorting-shelves-per-page', '18'))); + ->paginate(setting()->getInteger('lists-page-count-shelves', 18, 1, 1000)); $data = array_merge($commonData, ['shelves' => $shelves]); return view('home.shelves', $data); @@ -92,7 +92,7 @@ class HomeController extends Controller if ($homepageOption === 'books') { $books = $this->queries->books->visibleForListWithCover() ->orderBy($commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder()) - ->paginate(intval(setting('sorting-books-per-page', '18'))); + ->paginate(setting()->getInteger('lists-page-count-books', 18, 1, 1000)); $data = array_merge($commonData, ['books' => $books]); return view('home.books', $data); diff --git a/app/Entities/Controllers/BookController.php b/app/Entities/Controllers/BookController.php index 1c8009246..c94057fa9 100644 --- a/app/Entities/Controllers/BookController.php +++ b/app/Entities/Controllers/BookController.php @@ -52,7 +52,7 @@ class BookController extends Controller $books = $this->queries->visibleForListWithCover() ->orderBy($listOptions->getSort(), $listOptions->getOrder()) - ->paginate(intval(setting('sorting-books-per-page', '18'))); + ->paginate(setting()->getInteger('lists-page-count-books', 18, 1, 1000)); $recents = $this->isSignedIn() ? $this->queries->recentlyViewedForCurrentUser()->take(4)->get() : false; $popular = $this->queries->popularForList()->take(4)->get(); $new = $this->queries->visibleForList()->orderBy('created_at', 'desc')->take(4)->get(); diff --git a/app/Entities/Controllers/BookshelfController.php b/app/Entities/Controllers/BookshelfController.php index a7e1de159..f5f4a90bf 100644 --- a/app/Entities/Controllers/BookshelfController.php +++ b/app/Entities/Controllers/BookshelfController.php @@ -45,7 +45,7 @@ class BookshelfController extends Controller $shelves = $this->queries->visibleForListWithCover() ->orderBy($listOptions->getSort(), $listOptions->getOrder()) - ->paginate(intval(setting('sorting-shelves-per-page', '18'))); + ->paginate(setting()->getInteger('lists-page-count-shelves', 18, 1, 1000)); $recents = $this->isSignedIn() ? $this->queries->recentlyViewedForCurrentUser()->get() : false; $popular = $this->queries->popularForList()->get(); $new = $this->queries->visibleForList() diff --git a/app/Search/SearchController.php b/app/Search/SearchController.php index 9586beffb..2b9ea7974 100644 --- a/app/Search/SearchController.php +++ b/app/Search/SearchController.php @@ -25,10 +25,11 @@ class SearchController extends Controller $searchOpts = SearchOptions::fromRequest($request); $fullSearchString = $searchOpts->toString(); $page = intval($request->get('page', '0')) ?: 1; + $count = setting()->getInteger('lists-page-count-search', 18, 1, 1000); - $results = $this->searchRunner->searchEntities($searchOpts, 'all', $page, 20); + $results = $this->searchRunner->searchEntities($searchOpts, 'all', $page, $count); $formatter->format($results['results']->all(), $searchOpts); - $paginator = new LengthAwarePaginator($results['results'], $results['total'], 20, $page); + $paginator = new LengthAwarePaginator($results['results'], $results['total'], $count, $page); $paginator->setPath('/search'); $paginator->appends($request->except('page')); diff --git a/app/Settings/AppSettingsStore.php b/app/Settings/AppSettingsStore.php index e6fc466ba..e098d87f8 100644 --- a/app/Settings/AppSettingsStore.php +++ b/app/Settings/AppSettingsStore.php @@ -14,7 +14,7 @@ class AppSettingsStore ) { } - public function storeFromUpdateRequest(Request $request, string $category) + public function storeFromUpdateRequest(Request $request, string $category): void { $this->storeSimpleSettings($request); if ($category === 'customization') { @@ -76,7 +76,7 @@ class AppSettingsStore protected function storeSimpleSettings(Request $request): void { foreach ($request->all() as $name => $value) { - if (strpos($name, 'setting-') !== 0) { + if (!str_starts_with($name, 'setting-')) { continue; } @@ -85,7 +85,7 @@ class AppSettingsStore } } - protected function destroyExistingSettingImage(string $settingKey) + protected function destroyExistingSettingImage(string $settingKey): void { $existingVal = setting()->get($settingKey); if ($existingVal) { diff --git a/app/Settings/SettingService.php b/app/Settings/SettingService.php index 31debdaea..e0b136180 100644 --- a/app/Settings/SettingService.php +++ b/app/Settings/SettingService.php @@ -28,6 +28,21 @@ class SettingService return $this->formatValue($value, $default); } + /** + * Get a setting from the database as an integer. + * Returns the default value if not found or not an integer, and clamps the value to the given min/max range. + */ + public function getInteger(string $key, int $default, int $min = 0, int $max = PHP_INT_MAX): int + { + $value = $this->get($key, $default); + if (!is_numeric($value)) { + return $default; + } + + $int = intval($value); + return max($min, min($max, $int)); + } + /** * Get a value from the session instead of the main store option. */ diff --git a/lang/en/settings.php b/lang/en/settings.php index 4fcd2e2b4..1b5f9ce14 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -75,12 +75,8 @@ return [ 'reg_confirm_restrict_domain_placeholder' => 'No restriction set', // Sorting Settings - 'sorting' => 'Sorting', - 'sorting_shelves_per_page' => 'Shelves Per Page', - 'sorting_shelves_per_page_desc' => 'Sets the number of shelves shown per page in shelf listings.', - 'sorting_books_per_page' => 'Books Per Page', - 'sorting_books_per_page_desc' => 'Sets the number of books shown per page in book listings.', - 'sorting_book_default' => 'Default Book Sort', + 'sorting' => 'Lists & Sorting', + 'sorting_book_default' => 'Default Book Sort Rule', 'sorting_book_default_desc' => 'Select the default sort rule to apply to new books. This won\'t affect existing books, and can be overridden per-book.', 'sorting_rules' => 'Sort Rules', 'sorting_rules_desc' => 'These are predefined sorting operations which can be applied to content in the system.', @@ -107,6 +103,8 @@ return [ 'sort_rule_op_updated_date' => 'Updated Date', 'sort_rule_op_chapters_first' => 'Chapters First', 'sort_rule_op_chapters_last' => 'Chapters Last', + 'sorting_page_limits' => 'Per-Page Display Limits', + 'sorting_page_limits_desc' => 'Set how many items to show per-page in various lists within the system. Typically a lower amount will be more performant, while a higher amount avoids the need to click through multiple pages. Using an even multiple of 3 (18, 24, 30, etc...) is recommended.', // Maintenance settings 'maint' => 'Maintenance', diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index 12fb3385f..13a4232fc 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -348,6 +348,10 @@ input[type=color] { } } +.small-inputs input { + width: 150px; +} + .simple-code-input { background-color: #F8F8F8; font-family: monospace; diff --git a/resources/views/form/number.blade.php b/resources/views/form/number.blade.php index a37cd3694..b70b7e8db 100644 --- a/resources/views/form/number.blade.php +++ b/resources/views/form/number.blade.php @@ -6,7 +6,8 @@ @if($readonly ?? false) readonly="readonly" @endif @if($min ?? false) min="{{ $min }}" @endif @if($max ?? false) max="{{ $max }}" @endif - @if(isset($model) || old($name)) value="{{ old($name) ? old($name) : $model->$name}}" @endif> + @if($step ?? false) step="{{ $step }}" @endif + @if(isset($model) || old($name) || isset($value)) value="{{ old($name) ?? $model->$name ?? $value }}" @endif> @if($errors->has($name))
{{ $errors->first($name) }}
@endif diff --git a/resources/views/settings/categories/sorting.blade.php b/resources/views/settings/categories/sorting.blade.php index 4aff11bd2..0c9dc1f95 100644 --- a/resources/views/settings/categories/sorting.blade.php +++ b/resources/views/settings/categories/sorting.blade.php @@ -10,41 +10,30 @@ {{ csrf_field() }} -
-
- -

{{ trans('settings.sorting_shelves_per_page_desc') }}

-
-
- -
-
- -
-
- -

{{ trans('settings.sorting_books_per_page_desc') }}

-
-
- -
-
-
+
+
+ +

{{ trans('settings.sorting_page_limits_desc') }}

+
+
+ @php + $labelByKey = ['shelves' => trans('entities.shelves'), 'books' => trans('entities.books'), 'search' => trans('entities.search_results')]; + @endphp + @foreach($labelByKey as $key => $label) +
+ + @include('form.number', [ + 'name' => 'setting-lists-page-count-' . $key, + 'value' => setting()->getInteger('lists-page-count-' . $key, 18, 1, 1000), + 'min' => 1, + 'step' => 1, + ]) +
+ @endforeach +
+
+