Skip to content

Commit f77c2c0

Browse files
committed
added pagination items count selector in backend
1 parent b1508c1 commit f77c2c0

File tree

6 files changed

+189
-4
lines changed

6 files changed

+189
-4
lines changed

app/base/abstracts/Controllers/AdminManageModelsPage.php

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace App\Base\Abstracts\Controllers;
1515

16+
use App\Base\Abstracts\Models\BaseCollection;
1617
use App\Base\Abstracts\Models\BaseModel;
1718
use App\Base\Exceptions\PermissionDeniedException;
1819
use App\Site\Routing\RouteInfo;
@@ -26,6 +27,7 @@
2627
use Symfony\Component\HttpFoundation\Request;
2728
use App\Base\Abstracts\Models\FrontendModel;
2829
use Degami\Basics\Html\TagElement;
30+
use App\Site\Models\User;
2931

3032
/**
3133
* Base for admin page that manages a Model
@@ -62,6 +64,7 @@ public function __construct(
6264
) {
6365
parent::__construct($container, $request, $route_info);
6466
if ($this->template_data['action'] == 'list') {
67+
$this->addPaginationSizeSelector();
6568
$this->addNewButton();
6669

6770
$paginate_params = [
@@ -90,19 +93,43 @@ public function __construct(
9093

9194
$paginate_params['condition'] = array_filter($conditions);
9295
}
96+
97+
$itemsPerPage = $this->getItemsPerPage();
9398
/** @var \App\Base\Abstracts\Models\BaseCollection $collection */
9499
$collection = $this->containerCall([$this->getObjectClass(), 'getCollection']);
95100
$collection->addCondition($paginate_params['condition'])->addOrder($paginate_params['order']);
96-
$data = $this->containerCall([$collection, 'paginate']);
101+
$data = $this->containerCall([$collection, 'paginate'], ['page_size' => $itemsPerPage]);
97102
$this->template_data += [
98103
'table' => $this->getHtmlRenderer()->renderAdminTable($this->getTableElements($data['items']), $this->getTableHeader(), $this),
99104
'total' => $data['total'],
100105
'current_page' => $data['page'],
101-
'paginator' => $this->getHtmlRenderer()->renderPaginator($data['page'], $data['total'], $this),
106+
'paginator' => $this->getHtmlRenderer()->renderPaginator($data['page'], $data['total'], $this, $itemsPerPage, 5),
102107
];
103108
}
104109
}
105110

111+
/**
112+
* get items per page on listing
113+
*
114+
* @return int
115+
*/
116+
protected function getItemsPerPage() : int
117+
{
118+
/** @var User $user */
119+
$user = $this->getCurrentUser();
120+
121+
$uiSettings = $user->getUserSession()->getSessionKey('uiSettings');
122+
$currentRoute = $this->getRouteInfo()->getRouteName();
123+
124+
if (is_array($uiSettings) && isset($uiSettings[$currentRoute])) {
125+
if (isset($uiSettings[$currentRoute]['itemsPerPage'])) {
126+
return intval($uiSettings[$currentRoute]['itemsPerPage']);
127+
}
128+
}
129+
130+
return BaseCollection::ITEMS_PER_PAGE;
131+
}
132+
106133
/**
107134
* gets search parameters
108135
*
@@ -221,6 +248,36 @@ public function addNewButton()
221248
$this->addActionLink('new-btn', 'new-btn', $this->getHtmlRenderer()->getIcon('plus') . ' ' . $this->getUtils()->translate('New', $this->getCurrentLocale()), $this->getControllerUrl() . '?action=new', 'btn btn-sm btn-success');
222249
}
223250

251+
public function addPaginationSizeSelector()
252+
{
253+
// calculate options values, including value used for pagination
254+
$options = array_unique(array_merge([10, 25, 50, 200, 500], [$this->getItemsPerPage()]));
255+
sort($options);
256+
257+
$select = $this->containerMake(TagElement::class, ['options' => [
258+
'tag' => 'select',
259+
'id' => 'pagination-size-selector',
260+
'attributes' => [
261+
'class' => 'paginator-items-choice',
262+
'style' => 'width: 50px',
263+
],
264+
'children' => array_map(function($val) {
265+
$selected = [];
266+
if ($val == $this->getItemsPerPage()) {
267+
$selected = ['selected' => 'selected'];
268+
}
269+
return $this->containerMake(TagElement::class, ['options' => [
270+
'tag' => 'option',
271+
'value' => $val,
272+
'attributes' => [
273+
'class' => '',
274+
] + $selected,
275+
'text' => $val,
276+
]]);
277+
}, $options),
278+
]]);
279+
$this->action_buttons[] = __('Items per page'). ':' . $select;
280+
}
224281

225282
/**
226283
* gets action button html

app/base/abstracts/Controllers/AdminPage.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,12 @@ protected function prepareTemplate(): Template
151151
$this->getAssets()->addJs(
152152
"\$('#admin').appAdmin(" . json_encode(
153153
[
154+
'currentRoute' => $this->getRouteInfo()->getRouteName(),
154155
'checkLoggedUrl' => $this->getUrl('crud.app.site.controllers.admin.json.checksession'),
155156
'logoutUrl' => $this->getUrl('admin.logout'),
156157
'chatGPTUrl' => $this->getUrl('crud.app.site.controllers.admin.json.chatgpt'),
157158
'googleGeminiUrl' => $this->getUrl('crud.app.site.controllers.admin.json.googlegemini'),
159+
'uIsettingsUrl' => $this->getUrl('crud.app.site.controllers.admin.json.uisettings'),
158160
]
159161
) . ");"
160162
);

app/base/traits/AdminTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ protected function renderActionButtons(): string
118118
TagElement::class,
119119
['options' => [
120120
'tag' => 'li',
121-
'attributes' => ['class' => 'nav-item ml-1'],
121+
'attributes' => ['class' => 'nav-item ml-1 text-nowrap'],
122122
'text' => $button_html
123123
]]
124124
)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
/**
4+
* SiteBase
5+
* PHP Version 8.0
6+
*
7+
* @category CMS / Framework
8+
* @package Degami\Sitebase
9+
* @author Mirko De Grandis <degami@github.com>
10+
* @license MIT https://opensource.org/licenses/mit-license.php
11+
* @link https://github.com/degami/sitebase
12+
*/
13+
14+
namespace App\Site\Controllers\Admin\Json;
15+
16+
use App\Base\Abstracts\Controllers\AdminJsonPage;
17+
use DI\DependencyException;
18+
use DI\NotFoundException;
19+
use Exception;
20+
use Symfony\Component\HttpFoundation\Request;
21+
use App\Site\Models\User;
22+
23+
/**
24+
* UISettings Admin
25+
*/
26+
class UISettings extends AdminJsonPage
27+
{
28+
/**
29+
* {@inheritdocs}
30+
*
31+
* @return string
32+
*/
33+
protected function getAccessPermission(): string
34+
{
35+
return 'administer_site';
36+
}
37+
38+
/**
39+
* {@inheritdocs}
40+
*
41+
* @return array
42+
* @throws DependencyException
43+
* @throws NotFoundException
44+
*/
45+
protected function getJsonData(): array
46+
{
47+
$settings = $this->getSettingsData($this->getRequest());
48+
if (empty($settings) || !isset($settings['currentRoute'])) {
49+
throw new Exception("Missing settings content");
50+
}
51+
52+
$currentRoute = $settings['currentRoute'];
53+
// remove unuseful element
54+
unset($settings['currentRoute']);
55+
56+
/** @var User $user */
57+
$user = $this->getCurrentUser();
58+
$uiSettings = $user->getUserSession()->getSessionKey('uiSettings') ?? [];
59+
60+
// merge incoming data into existing
61+
$uiSettings[$currentRoute] = array_merge(
62+
$uiSettings[$currentRoute] ?? [],
63+
$settings
64+
);
65+
66+
// save data
67+
$user->getUserSession()->addSessionData('uiSettings', $uiSettings)->persist();
68+
69+
return ['success' => true, 'settings' => $user->getUserSession()->getSessionKey('uiSettings')];
70+
}
71+
72+
/**
73+
* @return string|null
74+
*/
75+
protected function getSettingsData(Request $request) : ?array
76+
{
77+
$content = json_decode($request->getContent(), true);
78+
if (is_array($content) && !empty($content)) {
79+
return $content;
80+
}
81+
82+
return null;
83+
}
84+
}

app/site/models/UserSession.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,22 @@ public function addSessionData(string $key, $value): UserSession
103103
return $this;
104104
}
105105

106+
/**
107+
* gets session data by key
108+
*
109+
* @param string $key
110+
* @return mixed
111+
*/
112+
public function getSessionKey(string $key): mixed
113+
{
114+
$session_data = $this->getNormalizedSessionData();
115+
if (array_key_exists($key, $session_data)) {
116+
return $session_data[$key];
117+
}
118+
119+
return null;
120+
}
121+
106122
/**
107123
* sets input array values as session values
108124
*

js/src/admin.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,19 @@
2929

3030
$elem.data('appAdmin', instance);
3131

32-
$('select:not(".select2-processed")', $elem).select2({'width':'100%'}).addClass('select2-processed');
32+
$('select:not(".select2-processed")', $elem).each(function(index, select){
33+
$(select).select2({'width': $(select).css('width') ? $(select).css('width') : '100%'}).addClass('select2-processed');
34+
});
35+
36+
$('select.paginator-items-choice').on('change', function(){
37+
$elem.appAdmin('updateUserUiSettings',
38+
{'currentRoute': $elem.appAdmin('getSettings').currentRoute, 'itemsPerPage': $(this).val()},
39+
function (data) {
40+
document.location.reload();
41+
}
42+
);
43+
});
44+
3345
$('a.inToolSidePanel[href]', $elem).click(function(evt){
3446
if($(this).attr('href') != '#') {
3547
evt.preventDefault();
@@ -221,6 +233,18 @@
221233
askGoogleGemini: function(text, target) {
222234
$(this).appAdmin('askAI', 'gemini', text, target);
223235
},
236+
updateUserUiSettings: function(settings, succesCallback) {
237+
var uIsettingsUrl = $(this).appAdmin('getSettings').uIsettingsUrl;
238+
$.ajax({
239+
type: "POST",
240+
url: uIsettingsUrl,
241+
data: JSON.stringify(settings),
242+
processData: false,
243+
contentType: 'application/json',
244+
success: succesCallback,
245+
error: function(xhr, ajaxOptions, thrownError) {}
246+
});
247+
},
224248
show : function( ) { },// IS
225249
hide : function( ) { },// GOOD
226250
update : function( content ) { }// !!!
@@ -231,5 +255,7 @@
231255
'logoutUrl': null,
232256
'chatGPTUrl': null,
233257
'googleGeminiUrl': null,
258+
'uIsettingsUrl': null,
259+
'currentRoute': null,
234260
}
235261
})(jQuery);

0 commit comments

Comments
 (0)