Merge pull request #2250 from coreos-inc/STORY-133211327-SSU-pagination

feat(super-users): paginate user tab
This commit is contained in:
Erica 2016-12-28 10:50:45 -05:00 committed by GitHub
commit 4c7445db81
4 changed files with 116 additions and 25 deletions

View file

@ -14,30 +14,40 @@
</span> </span>
</div> </div>
<div class="filter-box" collection="users" filter-model="search" filter-name="Users"></div> <div class="co-top-bar">
<span class="co-filter-box">
<table class="cor-table"> <span class="page-controls" total-count="orderedUsers.entries.length" current-page="options.page" page-size="usersPerPage"></span>
<input class="form-control" type="text" ng-model="options.filter" placeholder="Filter Users..." style="margin-right: 10px;">
</span>
</div>
<table class="cor-table" ng-if="orderedUsers.entries.length && !isLoading">
<thead> <thead>
<td style="width: 24px;"></td> <td style="width: 24px;"></td>
<td>Username</td> <td ng-class="tablePredicateClass('username', options.predicate, options.reverse)">
<td>E-mail address</td> <a ng-click="orderBy('username')">Username</a>
<td style="width: 24px;"></td> </td>
<td ng-class="tablePredicateClass('email', options.predicate, options.reverse)">
<a ng-click="orderBy('email')">E-mail address</a>
</td>
<td style="width: 24px;"></td>
</thead> </thead>
<tr ng-repeat="current_user in (users | filter:search | orderBy:'username')" <tr ng-repeat="current_user in orderedUsers.entries | slice
:(usersPerPage * options.page)
:(usersPerPage * (options.page + 1))"
class="user-row" class="user-row"
ng-class="current_user.enabled ? 'enabled': 'disabled'"> ng-class="current_user.enabled ? 'enabled': 'disabled'">
<td> <td>
<span class="avatar" data="current_user.avatar" size="24"></span> <span class="avatar" data="current_user.avatar" size="24"></span>
</td> </td>
<td> <td>
<span class="labels"> <span class="labels">
<span class="label label-success" ng-if="user.username == current_user.username">You</span> <span class="label label-success" ng-if="user.username == current_user.username">You</span>
<span class="label label-primary" <span class="label label-primary"
ng-if="current_user.super_user">Superuser</span> ng-if="current_user.super_user">Superuser</span>
<span class="label label-default" <span class="label label-default"
ng-if="!current_user.enabled">Disabled</span> ng-if="!current_user.enabled">Disabled</span>
</span> </span>
{{ current_user.username }} {{ current_user.username }}
</td> </td>
<td> <td>

View file

@ -9,30 +9,61 @@ angular.module('quay').directive('manageUserTab', function () {
transclude: true, transclude: true,
restrict: 'C', restrict: 'C',
scope: { scope: {
'isEnabled': '=isEnabled' 'isEnabled': '=isEnabled'
}, },
controller: function ($scope, $timeout, $location, $element, ApiService, UserService) { controller: function ($scope, $timeout, $location, $element, ApiService, UserService, TableService) {
$scope.user = UserService.currentUser();
$scope.users = null;
$scope.orderedUsers = [];
$scope.usersPerPage = 10;
$scope.newUser = {}; $scope.newUser = {};
$scope.createdUser = null; $scope.createdUser = null;
$scope.takeOwnershipInfo = null; $scope.takeOwnershipInfo = null;
$scope.options = {
'predicate': 'username',
'reverse': false,
'filter': null,
'page': 0
};
$scope.showCreateUser = function () { $scope.showCreateUser = function () {
$scope.createdUser = null; $scope.createdUser = null;
$('#createUserModal').modal('show'); $('#createUserModal').modal('show');
}; };
var sortUsers = function() {
if (!$scope.users) {return;}
$scope.orderedUsers = TableService.buildOrderedItems($scope.users, $scope.options,
['username', 'email'], []);
};
var loadUsersInternal = function () { var loadUsersInternal = function () {
ApiService.listAllUsers().then(function (resp) { ApiService.listAllUsers().then(function (resp) {
$scope.users = resp['users']; $scope.users = resp['users'];
sortUsers();
$scope.showInterface = true; $scope.showInterface = true;
}, function (resp) { }, function (resp) {
$scope.users = []; $scope.users = [];
$scope.usersError = ApiService.getErrorMessage(resp); $scope.usersError = ApiService.getErrorMessage(resp);
}); });
}; };
$scope.tablePredicateClass = function(name, predicate, reverse) {
if (name != predicate) {
return '';
}
return 'current ' + (reverse ? 'reversed' : '');
};
$scope.orderBy = function(predicate) {
if (predicate == $scope.options.predicate) {
$scope.options.reverse = !$scope.options.reverse;
return;
}
$scope.options.reverse = false;
$scope.options.predicate = predicate;
};
$scope.createUser = function () { $scope.createUser = function () {
$scope.creatingUser = true; $scope.creatingUser = true;
$scope.createdUser = null; $scope.createdUser = null;
@ -224,6 +255,10 @@ angular.module('quay').directive('manageUserTab', function () {
loadUsersInternal(); loadUsersInternal();
} }
}); });
$scope.$watch('options.predicate', sortUsers);
$scope.$watch('options.reverse', sortUsers);
$scope.$watch('options.filter', sortUsers);
} }
}; };
return directiveDefinitionObject; return directiveDefinitionObject;

View file

@ -10,7 +10,7 @@
}) })
}]); }]);
function SuperuserCtrl($scope, ApiService, Features, UserService, ContainerService, AngularPollChannel, CoreDialog) { function SuperuserCtrl($scope, ApiService, Features, UserService, ContainerService, AngularPollChannel, CoreDialog, TableService) {
if (!Features.SUPER_USERS) { if (!Features.SUPER_USERS) {
return; return;
} }
@ -31,6 +31,14 @@
$scope.serviceKeysActive = false; $scope.serviceKeysActive = false;
$scope.globalMessagesActive = false; $scope.globalMessagesActive = false;
$scope.manageUsersActive = false; $scope.manageUsersActive = false;
$scope.orderedOrgs = [];
$scope.orgsPerPage = 10;
$scope.options = {
'predicate': 'name',
'reverse': false,
'filter': null,
'page': 0,
}
$scope.loadMessageOfTheDay = function () { $scope.loadMessageOfTheDay = function () {
$scope.globalMessagesActive = true; $scope.globalMessagesActive = true;
@ -106,9 +114,16 @@
$scope.loadOrganizationsInternal(); $scope.loadOrganizationsInternal();
}; };
var sortOrgs = function() {
if (!$scope.organizations) {return;}
$scope.orderedOrgs = TableService.buildOrderedItems($scope.organizations, $scope.options,
['name', 'email'], []);
};
$scope.loadOrganizationsInternal = function() { $scope.loadOrganizationsInternal = function() {
$scope.organizationsResource = ApiService.listAllOrganizationsAsResource().get(function(resp) { $scope.organizationsResource = ApiService.listAllOrganizationsAsResource().get(function(resp) {
$scope.organizations = resp['organizations']; $scope.organizations = resp['organizations'];
sortOrgs();
return $scope.organizations; return $scope.organizations;
}); });
}; };
@ -117,6 +132,21 @@
$scope.manageUsersActive = true; $scope.manageUsersActive = true;
}; };
$scope.tablePredicateClass = function(name, predicate, reverse) {
if (name != predicate) {
return '';
}
return 'current ' + (reverse ? 'reversed' : '');
};
$scope.orderBy = function(predicate) {
if (predicate == $scope.options.predicate) {
$scope.options.reverse = !$scope.options.reverse;
return;
}
$scope.options.reverse = false;
$scope.options.predicate = predicate;
};
$scope.askDeleteOrganization = function(org) { $scope.askDeleteOrganization = function(org) {
bootbox.confirm('Are you sure you want to delete this organization? Its data will be deleted with it.', bootbox.confirm('Are you sure you want to delete this organization? Its data will be deleted with it.',
function(result) { function(result) {
@ -185,5 +215,9 @@
// Load the initial status. // Load the initial status.
$scope.checkStatus(); $scope.checkStatus();
$scope.$watch('options.predicate', sortOrgs);
$scope.$watch('options.reverse', sortOrgs);
$scope.$watch('options.filter', sortOrgs);
} }
}()); }());

View file

@ -111,17 +111,29 @@
<div class="manager-header" header-title="Organizations"> <div class="manager-header" header-title="Organizations">
</div> </div>
<div class="filter-box" collection="organization" filter-model="search" filter-name="Organizations"></div> <div class="co-top-bar">
<span class="co-filter-box">
<span class="page-controls" total-count="orderedOrgs.entries.length" current-page="options.page" page-size="orgsPerPage"></span>
<input class="form-control" type="text" ng-model="options.filter" placeholder="Filter Organizations..." style="margin-right: 10px;">
</span>
</div>
<table class="cor-table"> <table class="cor-table" ng-if="orderedOrgs.entries.length && !isLoading">
<thead> <thead>
<td style="width: 24px;"></td> <td style="width: 24px;"></td>
<td>Name</td>
<td>Admin E-mail</td> <td ng-class="tablePredicateClass('name', options.predicate, options.reverse)">
<a ng-click="orderBy('name')">Name</a>
</td>
<td ng-class="tablePredicateClass('email', options.predicate, options.reverse)">
<a ng-click="orderBy('email')">Admin Email</a>
</td>
<td style="width: 24px;"></td> <td style="width: 24px;"></td>
</thead> </thead>
<tr ng-repeat="current_org in (organizations | filter:search | orderBy:'name')" <tr ng-repeat="current_org in orderedOrgs.entries | slice
:(orgsPerPage * options.page)
:(orgsPerPage * (options.page + 1))"
class="org-row"> class="org-row">
<td> <td>
<span class="avatar" data="current_org.avatar" size="24"></span> <span class="avatar" data="current_org.avatar" size="24"></span>