diff --git a/static/directives/repo-view/repo-panel-settings.html b/static/directives/repo-view/repo-panel-settings.html
new file mode 100644
index 000000000..84a78a721
--- /dev/null
+++ b/static/directives/repo-view/repo-panel-settings.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
User and Robot Permissions
+
+
+
+
+
+
\ No newline at end of file
diff --git a/static/directives/repository-permissions-table.html b/static/directives/repository-permissions-table.html
new file mode 100644
index 000000000..3ce95c1d5
--- /dev/null
+++ b/static/directives/repository-permissions-table.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+ Account Name
+ Permissions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add New Permission
+
+
+
+
+
+
+
+
+
+
+ Add Permission
+
+
+
+
+
+
+ The selected user is outside of your organization. Are you sure you want to grant the user access to this repository?
+
+
\ No newline at end of file
diff --git a/static/js/directives/repo-view/repo-panel-settings.js b/static/js/directives/repo-view/repo-panel-settings.js
new file mode 100644
index 000000000..fd7edfda3
--- /dev/null
+++ b/static/js/directives/repo-view/repo-panel-settings.js
@@ -0,0 +1,19 @@
+/**
+ * An element which displays the settings panel for a repository view.
+ */
+angular.module('quay').directive('repoPanelSettings', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/repo-view/repo-panel-settings.html',
+ replace: false,
+ transclude: false,
+ restrict: 'C',
+ scope: {
+ 'repository': '=repository'
+ },
+ controller: function($scope, $element, ApiService) {
+ }
+ };
+ return directiveDefinitionObject;
+});
+
diff --git a/static/js/directives/ui/repository-permissions-table.js b/static/js/directives/ui/repository-permissions-table.js
new file mode 100644
index 000000000..fb3601d68
--- /dev/null
+++ b/static/js/directives/ui/repository-permissions-table.js
@@ -0,0 +1,136 @@
+/**
+ * An element which displays a table of permissions on a repository and allows them to be
+ * edited.
+ */
+angular.module('quay').directive('repositoryPermissionsTable', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/repository-permissions-table.html',
+ replace: false,
+ transclude: true,
+ restrict: 'C',
+ scope: {
+ 'repository': '=repository'
+ },
+ controller: function($scope, $element, ApiService, Restangular, UtilService) {
+ $scope.roles = [
+ { 'id': 'read', 'title': 'Read', 'kind': 'success' },
+ { 'id': 'write', 'title': 'Write', 'kind': 'success' },
+ { 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
+ ];
+
+ $scope.permissionResources = {'team': {}, 'user': {}};
+ $scope.permissionCache = {};
+ $scope.permissions = {};
+
+ var loadAllPermissions = function() {
+ if (!$scope.repository) { return; }
+ fetchPermissions('user');
+ fetchPermissions('team');
+ };
+
+ var fetchPermissions = function(kind) {
+ if ($scope.permissionResources[kind]['loading'] != null) {
+ return;
+ }
+
+ var params = {
+ 'repository': $scope.repository.namespace + '/' + $scope.repository.name
+ };
+
+ var Kind = kind[0].toUpperCase() + kind.substring(1);
+ var r = ApiService['listRepo' + Kind + 'PermissionsAsResource'](params).get(function(resp) {
+ $scope.permissions[kind] = resp.permissions;
+ return resp.permissions;
+ });
+
+ $scope.permissionResources[kind] = r;
+ };
+
+ $scope.$watch('repository', loadAllPermissions);
+ loadAllPermissions();
+
+ var getPermissionEndpoint = function(entityName, kind) {
+ var namespace = $scope.repository.namespace;
+ var name = $scope.repository.name;
+ var url = UtilService.getRestUrl('repository', namespace, name, 'permissions', kind, entityName);
+ return Restangular.one(url);
+ };
+
+ $scope.buildEntityForPermission = function(name, permission, kind) {
+ var key = name + ':' + kind;
+ if ($scope.permissionCache[key]) {
+ return $scope.permissionCache[key];
+ }
+
+ return $scope.permissionCache[key] = {
+ 'kind': kind,
+ 'name': name,
+ 'is_robot': permission.is_robot,
+ 'is_org_member': permission.is_org_member
+ };
+ };
+
+ $scope.grantPermission = function(entity, callback) {
+ $scope.addRole(entity.name, 'read', entity.kind, callback);
+ };
+
+ $scope.addNewPermission = function(entity) {
+ // Don't allow duplicates.
+ if (!entity || !entity.kind || $scope.permissions[entity.kind][entity.name]) { return; }
+
+ if (entity.is_org_member === false) {
+ $scope.grantPermissionInfo = {
+ 'entity': entity
+ };
+ return;
+ }
+
+ $scope.addRole(entity.name, 'read', entity.kind);
+ };
+
+ $scope.deleteRole = function(entityName, kind) {
+ var errorHandler = ApiService.errorDisplay('Cannot change permission', function(resp) {
+ if (resp.status == 409) {
+ return 'Cannot change permission as you do not have the authority';
+ }
+ });
+
+ var endpoint = getPermissionEndpoint(entityName, kind);
+ endpoint.customDELETE().then(function() {
+ delete $scope.permissions[kind][entityName];
+ }, errorHandler);
+ };
+
+ $scope.addRole = function(entityName, role, kind, opt_callback) {
+ var permission = {
+ 'role': role,
+ };
+
+ var errorHandler = ApiService.errorDisplay('Cannot change permission', function() {
+ opt_callback && opt_callback(false);
+ });
+
+ var endpoint = getPermissionEndpoint(entityName, kind);
+ endpoint.customPUT(permission).then(function(result) {
+ $scope.permissions[kind][entityName] = result;
+ opt_callback && opt_callback(true)
+ }, errorHandler);
+ };
+
+ $scope.setRole = function(role, entityName, kind) {
+ var errorDisplay = ApiService.errorDisplay(function(resp) {
+ $scope.permissions[kind][entityName] = {'role': currentRole};
+ });
+
+ var permission = $scope.permissions[kind][entityName];
+ var currentRole = permission.role;
+ permission.role = role;
+
+ var endpoint = getPermissionEndpoint(entityName, kind);
+ endpoint.customPUT(permission).then(function() {}, errorDisplay);
+ };
+ }
+ };
+ return directiveDefinitionObject;
+});
\ No newline at end of file
diff --git a/static/js/pages/repo-admin.js b/static/js/pages/repo-admin.js
index d45cf638e..f8a0f3f45 100644
--- a/static/js/pages/repo-admin.js
+++ b/static/js/pages/repo-admin.js
@@ -1,6 +1,6 @@
(function() {
/**
- * Repository admin/settings page.
+ * DEPRECATED: Repository admin/settings page.
*/
angular.module('quayPages').config(['pages', function(pages) {
pages.create('repo-admin', 'repo-admin.html', RepoAdminCtrl);
diff --git a/static/partials/repo-view.html b/static/partials/repo-view.html
index 113da0e78..b5d98eb79 100644
--- a/static/partials/repo-view.html
+++ b/static/partials/repo-view.html
@@ -80,9 +80,8 @@
-