- Fix tests

- Add new endpoints for retrieving the repo permissions for a robot account
- Have the robots list return the number of repositories for which there are permissions
- Other UI fixes
This commit is contained in:
Joseph Schorr 2015-03-31 18:50:43 -04:00
parent bb81c05c03
commit 1f5e6df678
16 changed files with 356 additions and 60 deletions

View file

@ -818,6 +818,17 @@
width: 30px;
}
.co-table td.caret-col {
width: 10px;
padding-left: 6px;
padding-right: 0px;
color: #aaa;
}
.co-table td.caret-col i.fa {
cursor: pointer;
}
.co-table .add-row-spacer td {
padding: 5px;
}

View file

@ -0,0 +1,86 @@
.robots-manager-element .manager-header {
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.robots-manager-element .manager-header h3 {
margin-bottom: 10px;
}
.robots-manager-element .robot a {
font-size: 16px;
cursor: pointer;
}
.robots-manager-element .robot .prefix {
color: #aaa;
}
.robots-manager-element .robot i {
margin-right: 10px;
}
.robots-manager-element .popup-input-button i.fa {
margin-right: 4px;
}
.robots-manager-element .empty {
color: #ccc;
}
.robots-manager-element tr.open td {
border-bottom: 1px solid transparent;
}
.robots-manager-element .permissions-table-wrapper {
margin-left: 0px;
border-left: 2px solid #ccc;
padding-left: 20px;
}
.robots-manager-element .permissions-table tbody tr:last-child td {
border-bottom: 0px;
}
.robots-manager-element .permissions-display-row {
position: relative;
padding-bottom: 20px;
}
.robots-manager-element .permissions-display-row td:first-child {
min-width: 300px;
}
.robots-manager-element .repo-circle {
color: #999;
display: inline-block;
position: relative;
background: #eee;
padding: 4px;
border-radius: 50%;
display: inline-block;
width: 46px;
height: 46px;
margin-right: 6px;
}
.robots-manager-element .repo-circle .fa-hdd-o {
font-size: 1.7em;
}
.robots-manager-element .repo-circle.no-background .fa-hdd-o {
font-size: 1.7em;
}
.robots-manager-element .repo-circle .fa-lock {
width: 16px;
height: 16px;
line-height: 16px;
font-size: 12px !important;
}
.robots-manager-element .repo-circle.no-background .fa-lock {
bottom: 5px;
right: 2px;
}

View file

@ -6,4 +6,20 @@
.org-view h3 {
margin-bottom: 20px;
margin-top: 0px;
}
.org-view .section-description-header {
padding-left: 40px;
position: relative;
margin-bottom: 20px;
}
.org-view .section-description-header:before {
font-family: FontAwesome;
content: "\f05a";
position: absolute;
top: 2px;
left: 6px;
font-size: 27px;
color: #888;
}

View file

@ -525,27 +525,6 @@ i.toggle-icon:hover {
visibility: hidden;
}
.robots-manager-element {
max-width: 800px;
}
.robots-manager-element .alert {
margin-bottom: 20px;
}
.robots-manager-element .robot a {
font-size: 16px;
cursor: pointer;
}
.robots-manager-element .robot .prefix {
color: #aaa;
}
.robots-manager-element .robot i {
margin-right: 10px;
}
.logs-view-element .header {
padding-bottom: 10px;
border-bottom: 1px solid #eee;

View file

@ -1,32 +1,102 @@
<div class="robots-manager-element">
<div class="quay-spinner" ng-show="loading"></div>
<div class="alert alert-info">Robot accounts allow for delegating access in multiple repositories to role-based accounts that you manage</div>
<div class="cor-loader" ng-show="loading"></div>
<div ng-show="!loading">
<div class="side-controls">
<span class="popup-input-button" pattern="ROBOT_PATTERN" placeholder="'Robot Account Name'"
submitted="createRobot(value)">
<i class="fa fa-wrench"></i> Create Robot Account
</span>
<div class="manager-header">
<div class="side-controls">
<span class="popup-input-button" pattern="ROBOT_PATTERN"
placeholder="'Robot Account Name'"
submitted="createRobot(value)">
<i class="fa fa-plus"></i> Create Robot Account
</span>
</div>
<h3>Robot Accounts</h3>
</div>
<table class="table">
<div class="manager-header section-description-header">
Robot Accounts are named tokens that can be granted permissions on multiple repositories
under this <span ng-if="organization">organization</span><span ng-if="!organization">user namespace</span>. They are typically used in environments where credentials will
be shared, such as deployment systems.
</div>
<div class="empty" ng-if="!robots.length">
<div class="empty-primary-msg">No robot accounts defined.</div>
<div class="empty-secondary-msg">
Click the "Create Robot Account" button above to create a robot account.
</div>
</div>
<table class="co-table" ng-if="robots.length">
<thead>
<th>Robot Account Name</th>
<th style="width: 150px"></th>
<td class="caret-col" ng-if="organization.is_admin"></td>
<td>Robot Account Name</td>
<td>Repository Permissions</td>
<td class="options-col"></td>
</thead>
<tr ng-repeat="robotInfo in robots">
<td class="robot">
<i class="fa fa-wrench"></i>
<a ng-click="showRobot(robotInfo)">
<span class="prefix">{{ getPrefix(robotInfo.name) }}+</span>{{ getShortenedName(robotInfo.name) }}
</a>
</td>
<td>
<span class="delete-ui" delete-title="'Delete Robot Account'" perform-delete="deleteRobot(robotInfo)"></span>
</td>
</tr>
<tbody ng-repeat="robotInfo in robots">
<tr ng-class="robotInfo.showing_permissions ? 'open' : 'closed'">
<td class="caret-col" ng-if="organization.is_admin">
<span ng-if="robotInfo.permission_count > 0" ng-click="showPermissions(robotInfo)">
<i class="fa"
ng-class="robotInfo.showing_permissions ? 'fa-caret-down' : 'fa-caret-right'"
data-title="View Permissions List" bs-tooltip></i>
</span>
</td>
<td class="robot">
<i class="fa fa-wrench"></i>
<a ng-click="showRobot(robotInfo)">
<span class="prefix">{{ getPrefix(robotInfo.name) }}+</span>{{ getShortenedName(robotInfo.name) }}
</a>
</td>
<td>
<span class="empty" ng-if="robotInfo.permission_count == 0">(No permissions on any repositories)</span>
<span ng-if="robotInfo.permission_count > 0">
Permissions on
<span class="anchor" href="javascript:void(0)" is-text-only="!organization.is_admin" ng-click="showPermissions(robotInfo)">{{ robotInfo.permission_count }}
<span ng-if="robotInfo.permission_count == 1">repository</span>
<span ng-if="robotInfo.permission_count > 1">repositories</span>
</span>
</span>
</td>
<td class="options-col">
<span class="cor-options-menu">
<span class="cor-option" option-click="showRobot(robotInfo)">
<i class="fa fa-key"></i> View Credentials
</span>
<span class="cor-option" option-click="deleteRobot(robotInfo)">
<i class="fa fa-times"></i> Delete Robot {{ robotInfo.name }}
</span>
</span>
</td>
</tr>
<tr ng-if="robotInfo.showing_permissions">
<td class="permissions-display-row" colspan="4">
<span class="cor-loader" ng-if="robotInfo.loading_permissions"></span>
<div class="permissions-table-wrapper">
<table class="permissions-table" ng-if="!robotInfo.loading_permissions">
<thead>
<td>Repository</td>
<td>Permission</td>
</thead>
<tr ng-repeat="permission in robotInfo.permissions">
<td>
<span class="repo-icon repo-circle no-background" repo="permission.repository"></span>
<a ng-href="/repository/{{ getPrefix(robotInfo.name) }}/{{ permission.repository.name }}">{{ getPrefix(robotInfo.name) }}/{{ permission.repository.name }}</a>
</td>
<td>
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role" roles="roles"
read-only="true"></span>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>

View file

@ -1,5 +1,6 @@
<div class="btn-group btn-group-sm">
<button ng-repeat="role in roles"
type="button" class="btn" ng-click="setRole(role.id)"
ng-class="(currentRole == role.id) ? ('active btn-' + role.kind) : 'btn-default'">{{ role.title }}</button>
ng-class="(currentRole == role.id) ? ('active btn-' + role.kind) : 'btn-default'"
ng-disabled="readOnly">{{ role.title }}</button>
</div>

View file

@ -13,6 +13,7 @@ angular.module('quay').directive('repositoryPermissionsTable', function () {
'repository': '=repository'
},
controller: function($scope, $element, ApiService, Restangular, UtilService) {
// TODO(jschorr): move this to a service.
$scope.roles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },

View file

@ -14,11 +14,36 @@ angular.module('quay').directive('robotsManager', function () {
},
controller: function($scope, $element, ApiService, $routeParams, CreateService) {
$scope.ROBOT_PATTERN = ROBOT_PATTERN;
// TODO(jschorr): move this to a service.
$scope.roles = [
{ 'id': 'read', 'title': 'Read', 'kind': 'success' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
];
$scope.robots = null;
$scope.loading = false;
$scope.shownRobot = null;
$scope.showRobotCounter = 0;
var loadRobotPermissions = function(info) {
var shortName = $scope.getShortenedName(info.name);
info.loading_permissions = true;
ApiService.getRobotPermissions($scope.organization, null, {'robot_shortname': shortName}).then(function(resp) {
info.permissions = resp.permissions;
info.loading_permissions = false;
}, ApiService.errorDisplay('Could not load robot permissions'));
};
$scope.showPermissions = function(robotInfo) {
robotInfo.showing_permissions = !robotInfo.showing_permissions;
if (robotInfo.showing_permissions) {
loadRobotPermissions(robotInfo);
}
};
$scope.regenerateToken = function(username) {
if (!username) { return; }

View file

@ -12,6 +12,7 @@ angular.module('quay').directive('roleGroup', function () {
scope: {
'roles': '=roles',
'currentRole': '=currentRole',
'readOnly': '=readOnly',
'roleChanged': '&roleChanged'
},
controller: function($scope, $element) {

View file

@ -18,10 +18,10 @@
<span class="cor-tab" tab-title="Teams" tab-target="#teams">
<i class="fa fa-users"></i>
</span>
<span class="cor-tab" tab-title="Robot Accounts" tab-target="#robots" ng-if="isAdmin">
<span class="cor-tab" tab-title="Robot Accounts" tab-target="#robots" ng-show="isAdmin">
<i class="fa fa-wrench"></i>
</span>
<span class="cor-tab" tab-title="Default Permissions" tab-target="#default" ng-if="isAdmin">
<span class="cor-tab" tab-title="Default Permissions" tab-target="#default" ng-show="isAdmin">
<i class="fa ci-stamp"></i>
</span>
<span class="cor-tab" tab-title="Billing" tab-target="#usage"
@ -33,15 +33,15 @@
<i class="fa ci-invoice"></i>
</span>
<span class="cor-tab" tab-title="Usage Logs" tab-target="#logs"
tab-init="showLogs()" ng-if="isAdmin">
tab-init="showLogs()" ng-show="isAdmin">
<i class="fa fa-bar-chart"></i>
</span>
<span class="cor-tab" tab-title="Applications" tab-target="#applications"
tab-init="showApplications()"ng-if="isAdmin">
tab-init="showApplications()" ng-show="isAdmin">
<i class="fa ci-application"></i>
</span>
<span class="cor-tab" tab-title="Organization Settings" tab-target="#settings"
ng-if="isAdmin">
ng-show="isAdmin">
<i class="fa fa-gears"></i>
</span>
</div> <!-- /cor-tabs -->
@ -65,7 +65,6 @@
<!-- Robot Accounts -->
<div id="robots" class="tab-pane">
<h3>Robot Accounts</h3>
<div class="robots-manager" organization="organization"></div>
</div>