diff --git a/endpoints/api.py b/endpoints/api.py index 9bd0352bb..495981145 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -589,22 +589,28 @@ def create_organization_prototype_permission(orgname): abort(404) details = request.get_json() - activating_user = details['activating_user']['name'] + activating_username = details['activating_user']['name'] delegate = details['delegate'] delegate_kind = delegate['kind'] delegate_name = delegate['name'] - delegate_user = delegate_name if delegate_kind == 'user' else None - delegate_team = delegate_name if delegate_kind == 'team' else None + delegate_username = delegate_name if delegate_kind == 'user' else None + delegate_teamname = delegate_name if delegate_kind == 'team' else None - role_name = details['role'] + activating_user = model.get_user(activating_username) + delegate_user = model.get_user(delegate_username) if delegate_username else None + delegate_team = model.get_organization_team(orgname, delegate_teamname) if delegate_teamname else None + + if not activating_user: + abort(404) if not delegate_user and not delegate_team: abort(400) + role_name = details['role'] prototype = model.add_prototype_permission(org, role_name, activating_user, delegate_user, delegate_team) - return jsonify(protoype_view(prototype)) + return jsonify(prototype_view(prototype)) abort(403) diff --git a/static/css/quay.css b/static/css/quay.css index 7ca8a5f27..af18ca590 100644 --- a/static/css/quay.css +++ b/static/css/quay.css @@ -73,10 +73,24 @@ top: 70px; } +.entity-search-element { + position: relative; +} + +.entity-search-element .entity-icon { + position: absolute; + top: 0px; + left: 8px; +} + .entity-search-element input { vertical-align: middle; } +.entity-search-element.persistent input { + padding-left: 28px; +} + .entity-search-element .twitter-typeahead { vertical-align: middle; } diff --git a/static/directives/entity-search.html b/static/directives/entity-search.html index 68f15b1cd..63b64070c 100644 --- a/static/directives/entity-search.html +++ b/static/directives/entity-search.html @@ -1,4 +1,12 @@ - + + + + + +
- @@ -22,9 +22,9 @@ - - Delegated User/Team + Delegated User/Robot/Team Permission @@ -55,5 +55,50 @@
+ + diff --git a/static/js/app.js b/static/js/app.js index 0f0db3a27..7d48216ec 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -1491,6 +1491,9 @@ quayApp.directive('prototypeManager', function () { }, controller: function($scope, $element, ApiService) { $scope.loading = false; + $scope.activatingForNew = null; + $scope.delegateForNew = null; + $scope.clearCounter = 0; $scope.roles = [ { 'id': 'read', 'title': 'Read', 'kind': 'success' }, @@ -1525,6 +1528,50 @@ quayApp.directive('prototypeManager', function () { }); }; + $scope.setRoleForNew = function(role) { + $scope.newRole = role; + }; + + $scope.showAddDialog = function() { + $scope.activatingForNew = null; + $scope.delegateForNew = null; + $scope.newRole = 'read'; + $scope.clearCounter++; + $('#addPermissionDialogModal').modal({}); + }; + + $scope.createPrototype = function() { + $scope.loading = true; + + var params = { + 'orgname': $scope.organization.name + }; + + var data = { + 'activating_user': $scope.activatingForNew, + 'delegate': $scope.delegateForNew, + 'role': $scope.newRole + }; + + ApiService.createOrganizationPrototypePermission(data, params).then(function(resp) { + $scope.prototypes.push(resp); + $scope.loading = false; + $('#addPermissionDialogModal').modal('hide'); + }, function(resp) { + $('#addPermissionDialogModal').modal('hide'); + bootbox.dialog({ + "message": resp.data ? resp.data : 'The permission could not be created', + "title": "Cannot create permission", + "buttons": { + "close": { + "label": "Close", + "className": "btn-primary" + } + } + }); + }); + }; + $scope.deletePrototype = function(prototype) { $scope.loading = true; @@ -1546,7 +1593,7 @@ quayApp.directive('prototypeManager', function () { "className": "btn-primary" } } - }); + }); }); }; @@ -1841,7 +1888,10 @@ quayApp.directive('entitySearch', function () { 'inputTitle': '=inputTitle', 'entitySelected': '=entitySelected', 'includeTeams': '=includeTeams', - 'isOrganization': '=isOrganization' + 'isOrganization': '=isOrganization', + 'isPersistent': '=isPersistent', + 'currentEntity': '=currentEntity', + 'clearNow': '=clearNow' }, controller: function($scope, $element, Restangular, UserService, ApiService) { $scope.lazyLoading = true; @@ -1915,10 +1965,27 @@ quayApp.directive('entitySearch', function () { entity['is_org_member'] = true; } - $scope.entitySelected(entity); + $scope.setEntityInternal(entity); }; - if (!$scope.entitySelected) { return; } + $scope.clearEntityInternal = function() { + $scope.currentEntity = null; + if ($scope.entitySelected) { + $scope.entitySelected(null); + } + }; + + $scope.setEntityInternal = function(entity) { + $(input).typeahead('setQuery', $scope.isPersistent ? entity.name : ''); + + if ($scope.isPersistent) { + $scope.currentEntity = entity; + } + + if ($scope.entitySelected) { + $scope.entitySelected(entity); + } + }; number++; @@ -1969,13 +2036,25 @@ quayApp.directive('entitySearch', function () { }, }); - $(input).on('typeahead:selected', function(e, datum) { - $(input).typeahead('setQuery', ''); + $(input).on('input', function(e) { $scope.$apply(function() { - $scope.entitySelected(datum.entity); + if ($scope.isPersistent) { + $scope.clearEntityInternal(); + } }); }); + $(input).on('typeahead:selected', function(e, datum) { + $scope.$apply(function() { + $scope.setEntityInternal(datum.entity); + }); + }); + + $scope.$watch('clearNow', function() { + $(input).typeahead('setQuery', ''); + $scope.clearEntityInternal(); + }); + $scope.$watch('inputTitle', function(title) { input.setAttribute('placeholder', title); });