diff --git a/themes/src/main/resources/theme/base/admin/resources/js/app.js b/themes/src/main/resources/theme/base/admin/resources/js/app.js
index f75e66dab3..e1f9891895 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -2802,3 +2802,81 @@ module.directive('kcOnReadFile', function ($parse) {
}
};
});
+
+module.controller('PagingCtrl', function ($scope) {
+ $scope.currentPageInput = 1;
+
+ $scope.firstPage = function() {
+ if (!$scope.hasPrevious()) return;
+ $scope.currentPage = 1;
+ $scope.currentPageInput = 1;
+ };
+
+ $scope.lastPage = function() {
+ if (!$scope.hasNext()) return;
+ $scope.currentPage = $scope.numberOfPages;
+ $scope.currentPageInput = $scope.numberOfPages;
+ };
+
+ $scope.previousPage = function() {
+ if (!$scope.hasPrevious()) return;
+ $scope.currentPage--;
+ $scope.currentPageInput = $scope.currentPage;
+ };
+
+ $scope.nextPage = function() {
+ if (!$scope.hasNext()) return;
+ $scope.currentPage++;
+ $scope.currentPageInput = $scope.currentPage;
+ };
+
+ $scope.hasNext = function() {
+ return $scope.currentPage < $scope.numberOfPages;
+ };
+
+ $scope.hasPrevious = function() {
+ return $scope.currentPage > 1;
+ };
+});
+
+module.directive('kcPaging', function () {
+ return {
+ scope: {
+ currentPage: '=',
+ currentPageInput: '=',
+ numberOfPages: '='
+ },
+ restrict: 'E',
+ replace: true,
+ controller: 'PagingCtrl',
+ templateUrl: resourceUrl + '/templates/kc-paging.html'
+ }
+});
+
+// Tests the page number input from currentPageInput to see
+// if it represents a valid page. If so, the current page is changed.
+module.directive('kcValidPage', function() {
+ return {
+ require: 'ngModel',
+ link: function(scope, element, attrs, ctrl) {
+ ctrl.$validators.inRange = function(modelValue, viewValue) {
+ if (viewValue >= 1 && viewValue <= scope.numberOfPages) {
+ scope.currentPage = viewValue;
+ }
+
+ return true;
+ }
+ }
+ }
+});
+
+// filter used for paged tables
+module.filter('startFrom', function () {
+ return function (input, start) {
+ if (input) {
+ start = +start;
+ return input.slice(start);
+ }
+ return [];
+ };
+});
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 4b33b14cb6..7d8de51ead 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -731,9 +731,21 @@ module.controller('ClientImportCtrl', function($scope, $location, $upload, realm
});
-module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $route, Dialog, Notifications) {
+module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $route, Dialog, Notifications, filterFilter) {
$scope.realm = realm;
$scope.clients = clients;
+ $scope.currentPage = 1;
+ $scope.currentPageInput = 1;
+ $scope.pageSize = 20;
+ $scope.numberOfPages = Math.ceil($scope.clients.length/$scope.pageSize);
+
+ $scope.$watch('search', function (newVal, oldVal) {
+ $scope.filtered = filterFilter($scope.clients, newVal);
+ $scope.totalItems = $scope.filtered.length;
+ $scope.numberOfPages = Math.ceil($scope.totalItems/$scope.pageSize);
+ $scope.currentPage = 1;
+ $scope.currentPageInput = 1;
+ }, true);
$scope.removeClient = function(client) {
Dialog.confirmDelete(client.clientId, 'client', function() {
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 568ebdf591..44ed51845c 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -1291,9 +1291,21 @@ module.controller('RealmRevocationCtrl', function($scope, Realm, RealmPushRevoca
});
-module.controller('RoleListCtrl', function($scope, $route, Dialog, Notifications, realm, roles, RoleById) {
+module.controller('RoleListCtrl', function($scope, $route, Dialog, Notifications, realm, roles, RoleById, filterFilter) {
$scope.realm = realm;
$scope.roles = roles;
+ $scope.currentPage = 1;
+ $scope.currentPageInput = 1;
+ $scope.pageSize = 20;
+ $scope.numberOfPages = Math.ceil($scope.roles.length/$scope.pageSize);
+
+ $scope.$watch('searchQuery', function (newVal, oldVal) {
+ $scope.filtered = filterFilter($scope.roles, {name: newVal});
+ $scope.totalItems = $scope.filtered.length;
+ $scope.numberOfPages = Math.ceil($scope.totalItems/$scope.pageSize);
+ $scope.currentPage = 1;
+ $scope.currentPageInput = 1;
+ }, true);
$scope.removeRole = function (role) {
Dialog.confirmDelete(role.name, 'role', function () {
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
index 7f796e9960..51aaa2009b 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
@@ -4,52 +4,53 @@
-
-
-
-
-
-
+
+ |
-
+
-
-
-
+
-
+
+
+
+
{{:: 'client-id' | translate}} |
- {{:: 'enabled' | translate}} |
- {{:: 'base-url' | translate}} |
- {{:: 'actions' | translate}} |
- |
+ ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
{{:: 'client-id' | translate}} | +{{:: 'enabled' | translate}} | +{{:: 'base-url' | translate}} | +{{:: 'actions' | translate}} | +||||||||||||||
{{client.clientId}} | -- | - {{client.rootUrl}}{{client.baseUrl}} - {{:: 'not-defined' | translate}} - | -{{:: 'edit' | translate}} | -{{:: 'export' | translate}} | -{{:: 'delete' | translate}} | -||||||||||||
{{:: 'no-results' | translate}} | -{{:: 'no-clients-available' | translate}} | -||||||||||||||||
{{client.clientId}} | ++ | + {{client.rootUrl}}{{client.baseUrl}} + {{:: 'not-defined' | translate}} + | +{{:: 'edit' | translate}} | +{{:: 'export' | translate}} | +{{:: 'delete' | translate}} | +||||||||||||
{{:: 'no-results' | translate}} | +{{:: 'no-clients-available' | translate}} | +
-
-
-
-
-
-
+
+ |
-
+
-
-
-
+
-
+
+
+
+
{{:: 'role-name' | translate}} |
- {{:: 'composite' | translate}} |
- {{:: 'description' | translate}} |
- {{:: 'actions' | translate}} |
- |
+ |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
{{:: 'role-name' | translate}} | +{{:: 'composite' | translate}} | +{{:: 'description' | translate}} | +{{:: 'actions' | translate}} | +|||||||||||
{{role.name}} | -- | {{role.description}} | -{{:: 'edit' | translate}} | -{{:: 'delete' | translate}} | -||||||||||
{{:: 'no-results' | translate}} | -{{:: 'no-realm-roles-available' | translate}} | -|||||||||||||
{{role.name}} | ++ | {{role.description}} | +{{:: 'edit' | translate}} | +{{:: 'delete' | translate}} | +||||||||||
{{:: 'no-results' | translate}} | +{{:: 'no-realm-roles-available' | translate}} | +