-
+
+ Create New Team
+
@@ -155,6 +149,8 @@
+
+
= 0 ||
- tagInfo.image_id.indexOf($scope.options.tagFilter) >= 0) {
- tags.push(tagInfo);
- }
}
// Sort the tags by the predicate and the reverse, and map the information.
var imageIDs = [];
- var ordered = orderBy(tags, $scope.options.predicate, $scope.options.reverse);
- var checked = [];
+ var ordered = TableService.buildOrderedItems(allTags, $scope.options,
+ ['name'], ['last_modified_datetime', 'size']).entries;
+ var checked = [];
var imageMap = {};
var imageIndexMap = {};
for (var i = 0; i < ordered.length; ++i) {
@@ -175,7 +167,7 @@ angular.module('quay').directive('repoPanelTags', function () {
$scope.$watch('options.predicate', setTagState);
$scope.$watch('options.reverse', setTagState);
- $scope.$watch('options.tagFilter', setTagState);
+ $scope.$watch('options.filter', setTagState);
$scope.$watch('options.page', function(page) {
if (page != null && $scope.checkedTags) {
diff --git a/static/js/directives/ui/create-entity-dialog.js b/static/js/directives/ui/create-entity-dialog.js
new file mode 100644
index 000000000..781e07747
--- /dev/null
+++ b/static/js/directives/ui/create-entity-dialog.js
@@ -0,0 +1,202 @@
+/**
+ * An element which displays a create entity dialog.
+ */
+angular.module('quay').directive('createEntityDialog', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/create-entity-dialog.html',
+ replace: false,
+ transclude: true,
+ restrict: 'C',
+ scope: {
+ 'info': '=info',
+
+ 'entityKind': '@entityKind',
+ 'entityTitle': '@entityTitle',
+ 'entityIcon': '@entityIcon',
+ 'entityNameRegex': '@entityNameRegex',
+
+ 'entityCreateRequested': '&entityCreateRequested',
+ 'entityCreateCompleted': '&entityCreateCompleted'
+ },
+
+ controller: function($scope, $element, ApiService, UIService, TableService, RolesService, UserService) {
+ $scope.TableService = TableService;
+
+ $scope.options = {
+ 'predicate': 'last_modified_datetime',
+ 'reverse': false,
+ 'filter': ''
+ };
+
+ var handleRepoCheckChange = function() {
+ $scope.repositories.forEach(function(repo) {
+ if ($scope.checkedRepos.isChecked(repo)) {
+ if (repo['permission'] == 'none') {
+ repo['permission'] = 'read';
+ }
+ } else {
+ repo['permission'] = 'none';
+ }
+ });
+ };
+
+ $scope.$on('$destroy', function() {
+ if ($scope.inBody) {
+ document.body.removeChild($element[0]);
+ }
+ });
+
+ $scope.setRole = function(role, repo) {
+ repo['permission'] = role;
+
+ if (role == 'none') {
+ $scope.checkedRepos.uncheckItem(repo);
+ } else {
+ $scope.checkedRepos.checkItem(repo);
+ }
+ };
+
+ $scope.hide = function() {
+ $element.find('.modal').modal('hide');
+ if ($scope.entity) {
+ $scope.entityCreateCompleted({'entity': $scope.entity});
+ $scope.entity = null;
+ }
+ };
+
+ $scope.show = function() {
+ $scope.entityName = null;
+ $scope.entity = null;
+ $scope.creating = false;
+ $scope.view = 'enterName';
+ $scope.enterNameForm.$setPristine(true);
+
+ // Move the dialog to the body to prevent it from nesting if called
+ // from within another dialog.
+ $element.find('.modal').modal({});
+ $scope.inBody = true;
+ document.body.appendChild($element[0]);
+ };
+
+ var setRepoState = function() {
+ if (!$scope.repositories) {
+ return;
+ }
+
+ $scope.orderedRepositories = TableService.buildOrderedItems($scope.repositories, $scope.options,
+ ['name', 'permission'],
+ ['last_modified_datetime']);
+ };
+
+ var entityCreateCallback = function(entity) {
+ if (!entity || $scope.info.skip_permissions) {
+ $scope.entity = entity;
+ $scope.hide();
+ return;
+ }
+
+ // Load the repositories under the entity's namespace.
+ var params = {
+ 'namespace': $scope.info.namespace,
+ 'last_modified': true
+ };
+
+ ApiService.listRepos(null, params).then(function(resp) {
+ $scope.view = 'addperms';
+ $scope.entity = entity;
+
+ var repos = [];
+ resp['repositories'].forEach(function(repo) {
+ repos.push({
+ 'namespace': repo.namespace,
+ 'name': repo.name,
+ 'last_modified': repo.last_modified,
+ 'last_modified_datetime': TableService.getReversedTimestamp(repo.last_modified),
+ 'permission': 'none'
+ });
+ });
+
+ if (repos.length == 0) {
+ $scope.hide();
+ return;
+ }
+
+ $scope.repositories = repos;
+ $scope.checkedRepos = UIService.createCheckStateController($scope.repositories, 'name');
+ $scope.checkedRepos.listen(handleRepoCheckChange);
+
+ if ($scope.info.repository) {
+ repos.forEach(function(repo) {
+ if (repo['namespace'] == $scope.info.repository.namespace &&
+ repo['name'] == $scope.info.repository.name) {
+ $scope.checkedRepos.checkItem(repo);
+ $scope.options.filter = $scope.info.repository.name;
+ }
+ });
+ }
+
+ setRepoState();
+ }, ApiService.errorDisplay('Could not load repositories'));
+ };
+
+ $scope.addPermissions = function() {
+ $scope.view = 'addingperms';
+
+ var repos = $scope.checkedRepos.checked;
+ var counter = 0;
+
+ var addPerm = function() {
+ if (counter >= repos.length) {
+ $scope.hide();
+ return;
+ }
+
+ var repo = repos[counter];
+ RolesService.setRepositoryRole(repo, repo.permission, $scope.entityKind, $scope.entity.name,
+ function(status) {
+ if (status) {
+ counter++;
+ addPerm();
+ } else {
+ $scope.hide();
+ }
+ });
+ };
+
+ addPerm();
+ };
+
+ $scope.createEntity = function() {
+ $scope.view = 'creating';
+ $scope.entityCreateRequested({
+ 'name': $scope.entityName,
+ 'callback': entityCreateCallback
+ });
+ };
+
+ $scope.$watch('options.predicate', setRepoState);
+ $scope.$watch('options.reverse', setRepoState);
+ $scope.$watch('options.filter', setRepoState);
+
+ $scope.$watch('entityNameRegex', function(r) {
+ if (r) {
+ $scope.entityNameRegexObj = new RegExp(r);
+ }
+ });
+
+ $scope.$watch('info', function(info) {
+ if (!info || !info.namespace) {
+ $scope.hide();
+ return;
+ }
+
+ $scope.namespace = UserService.getNamespace(info.namespace);
+ if ($scope.namespace) {
+ $scope.show();
+ }
+ });
+ }
+ };
+ return directiveDefinitionObject;
+});
\ No newline at end of file
diff --git a/static/js/directives/ui/create-robot-dialog.js b/static/js/directives/ui/create-robot-dialog.js
new file mode 100644
index 000000000..59beecc90
--- /dev/null
+++ b/static/js/directives/ui/create-robot-dialog.js
@@ -0,0 +1,43 @@
+/**
+ * An element which displays a dialog for creating a robot account.
+ */
+angular.module('quay').directive('createRobotDialog', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/create-robot-dialog.html',
+ replace: false,
+ transclude: true,
+ restrict: 'C',
+ scope: {
+ 'info': '=info',
+ 'robotCreated': '&robotCreated'
+ },
+ controller: function($scope, $element, ApiService, UserService) {
+ $scope.ROBOT_PATTERN = ROBOT_PATTERN;
+
+ $scope.robotFinished = function(robot) {
+ $scope.robotCreated({'robot': robot});
+ };
+
+ $scope.createRobot = function(name, callback) {
+ var organization = $scope.info.namespace;
+ if (!UserService.isOrganization(organization)) {
+ organization = null;
+ }
+
+ var params = {
+ 'robot_shortname': name
+ };
+
+ var errorDisplay = ApiService.errorDisplay('Cannot create robot account', function() {
+ callback(null);
+ });
+
+ ApiService.createRobot(organization, null, params).then(function(resp) {
+ callback(resp);
+ }, errorDisplay);
+ };
+ }
+ };
+ return directiveDefinitionObject;
+});
\ No newline at end of file
diff --git a/static/js/directives/ui/create-team-dialog.js b/static/js/directives/ui/create-team-dialog.js
new file mode 100644
index 000000000..4d63e57b8
--- /dev/null
+++ b/static/js/directives/ui/create-team-dialog.js
@@ -0,0 +1,44 @@
+/**
+ * An element which displays a dialog for creating a team.
+ */
+angular.module('quay').directive('createTeamDialog', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/create-team-dialog.html',
+ replace: false,
+ transclude: true,
+ restrict: 'C',
+ scope: {
+ 'info': '=info',
+ 'teamCreated': '&teamCreated'
+ },
+ controller: function($scope, $element, ApiService, UserService) {
+ $scope.TEAM_PATTERN = TEAM_PATTERN;
+
+ $scope.teamFinished = function(team) {
+ $scope.teamCreated({'team': team});
+ };
+
+ $scope.createTeam = function(name, callback) {
+ var data = {
+ 'name': name,
+ 'role': 'member'
+ };
+
+ var params = {
+ 'orgname': $scope.info.namespace,
+ 'teamname': name
+ };
+
+ var errorDisplay = ApiService.errorDisplay('Cannot create team', function() {
+ callback(null);
+ });
+
+ ApiService.updateOrganizationTeam(data, params).then(function(resp) {
+ callback(resp);
+ }, errorDisplay);
+ };
+ }
+ };
+ return directiveDefinitionObject;
+});
\ No newline at end of file
diff --git a/static/js/directives/ui/credentials-dialog.js b/static/js/directives/ui/credentials-dialog.js
index d20a4624c..52e1aec48 100644
--- a/static/js/directives/ui/credentials-dialog.js
+++ b/static/js/directives/ui/credentials-dialog.js
@@ -22,6 +22,12 @@ angular.module('quay').directive('credentialsDialog', function () {
$scope.rkt = {};
$scope.docker = {};
+ $scope.$on('$destroy', function() {
+ if ($scope.inBody) {
+ document.body.removeChild($element[0]);
+ }
+ });
+
// Generate a unique ID for the dialog.
if (!$rootScope.credentialsDialogCounter) {
$rootScope.credentialsDialogCounter = 0;
@@ -36,6 +42,11 @@ angular.module('quay').directive('credentialsDialog', function () {
$scope.show = function() {
$element.find('.modal').modal({});
+
+ // Move the dialog to the body to prevent it from being affected
+ // by being placed inside other tables.
+ $scope.inBody = true;
+ document.body.appendChild($element[0]);
};
$scope.$watch('credentials', function(credentials) {
diff --git a/static/js/directives/ui/entity-search.js b/static/js/directives/ui/entity-search.js
index 565103ca0..874908848 100644
--- a/static/js/directives/ui/entity-search.js
+++ b/static/js/directives/ui/entity-search.js
@@ -18,6 +18,8 @@ angular.module('quay').directive('entitySearch', function () {
scope: {
'namespace': '=namespace',
'placeholder': '=placeholder',
+ 'forRepository': '=forRepository',
+ 'skipPermissions': '=skipPermissions',
// Default: ['user', 'team', 'robot']
'allowedEntities': '=allowedEntities',
@@ -41,7 +43,7 @@ angular.module('quay').directive('entitySearch', function () {
// True if the menu should pull right.
'pullRight': '@pullRight'
},
- controller: function($rootScope, $scope, $element, Restangular, UserService, ApiService, UtilService, Config, CreateService) {
+ controller: function($rootScope, $scope, $element, Restangular, UserService, ApiService, UtilService, Config) {
$scope.lazyLoading = true;
$scope.teams = null;
@@ -55,6 +57,8 @@ angular.module('quay').directive('entitySearch', function () {
$scope.includeOrgs = false;
$scope.currentEntityInternal = $scope.currentEntity;
+ $scope.createRobotInfo = null;
+ $scope.createTeamInfo = null;
$scope.Config = Config;
@@ -91,18 +95,30 @@ angular.module('quay').directive('entitySearch', function () {
}
};
- $scope.createTeam = function() {
- CreateService.askCreateTeam($scope.namespace, function(created) {
- $scope.setEntity(created.name, 'team', false, created.avatar);
- $scope.teams[created.name] = created;
- });
+ $scope.askCreateTeam = function() {
+ $scope.createTeamInfo = {
+ 'namespace': $scope.namespace,
+ 'repository': $scope.forRepository,
+ 'skip_permissions': $scope.skipPermissions
+ };
};
- $scope.createRobot = function() {
- CreateService.askCreateRobot($scope.namespace, function(created) {
- $scope.setEntity(created.name, 'user', true, created.avatar);
- $scope.robots.push(created);
- });
+ $scope.askCreateRobot = function() {
+ $scope.createRobotInfo = {
+ 'namespace': $scope.namespace,
+ 'repository': $scope.forRepository,
+ 'skip_permissions': $scope.skipPermissions
+ };
+ };
+
+ $scope.handleTeamCreated = function(created) {
+ $scope.setEntity(created.name, 'team', false, created.avatar);
+ $scope.teams[created.name] = created;
+ };
+
+ $scope.handleRobotCreated = function(created) {
+ $scope.setEntity(created.name, 'user', true, created.avatar);
+ $scope.robots.push(created);
};
$scope.setEntity = function(name, kind, is_robot, avatar) {
diff --git a/static/js/directives/ui/header-bar.js b/static/js/directives/ui/header-bar.js
index 3617fdcdd..8b88d886f 100644
--- a/static/js/directives/ui/header-bar.js
+++ b/static/js/directives/ui/header-bar.js
@@ -13,7 +13,7 @@ angular.module('quay').directive('headerBar', function () {
scope: {
},
controller: function($rootScope, $scope, $element, $location, $timeout, hotkeys, UserService,
- PlanService, ApiService, NotificationService, Config, CreateService, Features,
+ PlanService, ApiService, NotificationService, Config, Features,
DocumentationService, ExternalLoginService) {
$scope.externalSigninUrl = ExternalLoginService.getSingleSigninUrl();
@@ -268,24 +268,36 @@ angular.module('quay').directive('headerBar', function () {
$location.url('/repository/' + context.repository.namespace + '/' + context.repository.name + '/build/' + build.id);
};
- $scope.createRobot = function(context) {
+ $scope.handleRobotCreated = function(created, context) {
var namespace = $scope.getNamespace(context);
- CreateService.askCreateRobot(namespace, function(created) {
- if (UserService.isOrganization(namespace)) {
- $location.url('/organization/' + namespace + '?tab=robots&showRobot=' + created.name);
- } else {
- $location.url('/user/' + namespace + '?tab=robots&showRobot=' + created.name);
- }
- });
+ if (UserService.isOrganization(namespace)) {
+ $location.url('/organization/' + namespace + '?tab=robots&showRobot=' + created.name);
+ } else {
+ $location.url('/user/' + namespace + '?tab=robots&showRobot=' + created.name);
+ }
};
- $scope.createTeam = function(context) {
+ $scope.handleTeamCreated = function(created, context) {
+ var namespace = $scope.getNamespace(context);
+ $location.url('/organization/' + namespace + '/teams/' + created.name);
+ };
+
+ $scope.askCreateRobot = function(context) {
var namespace = $scope.getNamespace(context);
if (!namespace || !UserService.isNamespaceAdmin(namespace)) { return; }
- CreateService.askCreateTeam(namespace, function(created) {
- $location.url('/organization/' + namespace + '/teams/' + created.name);
- });
+ $scope.createRobotInfo = {
+ 'namespace': namespace
+ };
+ };
+
+ $scope.askCreateTeam = function(context) {
+ var namespace = $scope.getNamespace(context);
+ if (!namespace || !UserService.isNamespaceAdmin(namespace)) { return; }
+
+ $scope.createTeamInfo = {
+ 'namespace': namespace
+ };
};
}
};
diff --git a/static/js/directives/ui/repo-list-table.js b/static/js/directives/ui/repo-list-table.js
index 7a5e98e53..4b9b59fdd 100644
--- a/static/js/directives/ui/repo-list-table.js
+++ b/static/js/directives/ui/repo-list-table.js
@@ -13,30 +13,22 @@ angular.module('quay').directive('repoListTable', function () {
'namespaces': '=namespaces',
'starToggled': '&starToggled'
},
- controller: function($scope, $element, $filter) {
- var orderBy = $filter('orderBy');
-
+ controller: function($scope, $element, $filter, TableService) {
$scope.repositories = null;
$scope.orderedRepositories = [];
$scope.maxPopularity = 0;
$scope.options = {
'predicate': 'popularity',
- 'reverse': true
+ 'reverse': false,
+ 'filter': null
};
var buildOrderedRepositories = function() {
if (!$scope.repositories) { return; }
- var modifier = $scope.options.reverse ? '-' : '';
- var fields = [modifier + $scope.options.predicate];
- // Secondary ordering by full name.
- if ($scope.options.predicate != 'full_name') {
- fields.push('full_name');
- }
-
- var ordered = orderBy($scope.repositories, fields, false);
- $scope.orderedRepositories = ordered;
+ $scope.orderedRepositories = TableService.buildOrderedItems($scope.repositories, $scope.options,
+ [], ['last_modified_datetime', 'popularity'])
};
$scope.tablePredicateClass = function(name, predicate, reverse) {
@@ -92,7 +84,7 @@ angular.module('quay').directive('repoListTable', function () {
(resource.value || []).forEach(function(repository) {
var repositoryInfo = $.extend(repository, {
'full_name': repository.namespace + '/' + repository.name,
- 'last_modified_datetime': (new Date(repository.last_modified || 0)).valueOf() * (-1)
+ 'last_modified_datetime': TableService.getReversedTimestamp(repository.last_modified),
});
$scope.repositories.push(repositoryInfo);
diff --git a/static/js/directives/ui/repository-permissions-table.js b/static/js/directives/ui/repository-permissions-table.js
index a4e98b361..a832ac207 100644
--- a/static/js/directives/ui/repository-permissions-table.js
+++ b/static/js/directives/ui/repository-permissions-table.js
@@ -28,7 +28,7 @@ angular.module('quay').directive('repositoryPermissionsTable', function () {
'repository': '=repository',
'isEnabled': '=isEnabled'
},
- controller: function($scope, $element, ApiService, Restangular, UtilService, RolesService) {
+ controller: function($scope, $element, ApiService, RolesService) {
$scope.permissionResources = {'team': {}, 'user': {}};
$scope.permissionCache = {};
$scope.permissions = {};
@@ -69,13 +69,6 @@ angular.module('quay').directive('repositoryPermissionsTable', function () {
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(permission, kind) {
var key = permission.name + ':' + kind;
if ($scope.permissionCache[key]) {
@@ -146,51 +139,36 @@ angular.module('quay').directive('repositoryPermissionsTable', function () {
};
$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';
+ RolesService.deleteRepositoryRole($scope.repository, kind, entityName, function(status) {
+ if (status) {
+ delete $scope.permissions[kind][entityName];
}
});
-
- 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);
+ RolesService.setRepositoryRole($scope.repository, role, kind, entityName, function(status, result) {
$scope.addPermissionInfo = {
'role': readRole
};
+
+ if (status) {
+ $scope.permissions[kind][entityName] = result;
+ }
+
+ opt_callback && opt_callback(status);
});
-
- var endpoint = getPermissionEndpoint(entityName, kind);
- endpoint.customPUT(permission).then(function(result) {
- $scope.permissions[kind][entityName] = result;
- $scope.addPermissionInfo = {
- 'role': readRole
- };
- 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 currentRole = $scope.permissions[kind][entityName].role;
+ RolesService.setRepositoryRole($scope.repository, role, kind, entityName, function(status) {
+ if (status) {
+ $scope.permissions[kind][entityName]['role'] = role;
+ } else {
+ $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);
};
}
};
diff --git a/static/js/directives/ui/robots-manager.js b/static/js/directives/ui/robots-manager.js
index 0f1e9ded1..d34833f69 100644
--- a/static/js/directives/ui/robots-manager.js
+++ b/static/js/directives/ui/robots-manager.js
@@ -13,15 +13,14 @@ angular.module('quay').directive('robotsManager', function () {
'user': '=user',
'isEnabled': '=isEnabled'
},
- controller: function($scope, $element, ApiService, $routeParams, $location, CreateService,
- Config, $rootScope) {
- $scope.ROBOT_PATTERN = ROBOT_PATTERN;
-
+ controller: function($scope, $element, ApiService, $routeParams, $location, Config, $rootScope) {
$scope.robots = null;
$scope.loading = false;
$scope.Config = Config;
$scope.feedback = null;
+
$scope.robotDisplayInfo = null;
+ $scope.createRobotInfo = null;
// Listen for route changes and update the tabs accordingly.
var locationListener = $rootScope.$on('$routeUpdate', function(){
@@ -96,22 +95,10 @@ angular.module('quay').directive('robotsManager', function () {
return name.substr(0, plus);
};
- $scope.createRobot = function(name) {
- if (!name) { return; }
-
- CreateService.createRobotAccount(ApiService, !!$scope.organization, $scope.organization ? $scope.organization.name : '', name,
- function(created) {
- created.teams = [];
- created.repositories = [];
- $scope.robots.push(created);
- $scope.feedback = {
- 'kind': 'success',
- 'message': 'Robot account {robot} was created',
- 'data': {
- 'robot': name
- }
- };
- });
+ $scope.askCreateRobot = function() {
+ $scope.createRobotInfo = {
+ 'namespace': $scope.organization ? $scope.organization.name : $scope.user.username
+ };
};
$scope.deleteRobot = function(info) {
@@ -131,7 +118,6 @@ angular.module('quay').directive('robotsManager', function () {
}, ApiService.errorDisplay('Cannot delete robot account'));
};
-
$scope.askDeleteRobot = function(info) {
bootbox.confirm('Are you sure you want to delete robot ' + info.name + '?', function(resp) {
if (resp) {
@@ -140,6 +126,10 @@ angular.module('quay').directive('robotsManager', function () {
});
};
+ $scope.robotCreated = function() {
+ update();
+ };
+
var update = function() {
if (!$scope.user && !$scope.organization) { return; }
if ($scope.loading || !$scope.isEnabled) { return; }
diff --git a/static/js/directives/ui/teams-manager.js b/static/js/directives/ui/teams-manager.js
index 9e67ca853..80a09efe1 100644
--- a/static/js/directives/ui/teams-manager.js
+++ b/static/js/directives/ui/teams-manager.js
@@ -12,8 +12,7 @@ angular.module('quay').directive('teamsManager', function () {
'organization': '=organization',
'isEnabled': '=isEnabled'
},
- controller: function($scope, $element, ApiService, CreateService, $timeout, UserService) {
- $scope.TEAM_PATTERN = TEAM_PATTERN;
+ controller: function($scope, $element, ApiService, $timeout, UserService) {
$scope.teamRoles = [
{ 'id': 'member', 'title': 'Member', 'kind': 'default' },
{ 'id': 'creator', 'title': 'Creator', 'kind': 'success' },
@@ -27,6 +26,7 @@ angular.module('quay').directive('teamsManager', function () {
$scope.showingMembers = false;
$scope.fullMemberList = null;
$scope.feedback = null;
+ $scope.createTeamInfo = null;
var loadTeamMembers = function() {
if (!$scope.organization || !$scope.isEnabled) { return; }
@@ -107,35 +107,27 @@ angular.module('quay').directive('teamsManager', function () {
}, errorHandler);
};
- $scope.createTeam = function(teamname) {
- if (!teamname) {
- return;
- }
+ $scope.askCreateTeam = function(teamname) {
+ $scope.createTeamInfo = {
+ 'namespace': $scope.organization.name
+ };
+ };
- if ($scope.organization.teams[teamname]) {
- $('#team-' + teamname).removeClass('highlight');
- setTimeout(function() {
- $('#team-' + teamname).addClass('highlight');
- }, 10);
- return;
- }
+ $scope.handleTeamCreated = function(created) {
+ var teamname = created.name;
+ $scope.organization.teams[teamname] = created;
+ $scope.members[teamname] = {};
+ $scope.members[teamname].members = [];
+ $scope.organization.ordered_teams.push(teamname);
+ $scope.orderedTeams.push(created);
- var orgname = $scope.organization.name;
- CreateService.createOrganizationTeam(ApiService, orgname, teamname, function(created) {
- $scope.organization.teams[teamname] = created;
- $scope.members[teamname] = {};
- $scope.members[teamname].members = [];
- $scope.organization.ordered_teams.push(teamname);
- $scope.orderedTeams.push(created);
-
- $scope.feedback = {
- 'kind': 'success',
- 'message': 'Team {team} created',
- 'data': {
- 'team': teamname
- }
- };
- });
+ $scope.feedback = {
+ 'kind': 'success',
+ 'message': 'Team {team} created',
+ 'data': {
+ 'team': teamname
+ }
+ };
};
$scope.askDeleteTeam = function(teamname) {
diff --git a/static/js/pages/user-view.js b/static/js/pages/user-view.js
index 92efb21d6..30cc4d719 100644
--- a/static/js/pages/user-view.js
+++ b/static/js/pages/user-view.js
@@ -41,6 +41,7 @@
var loadUser = function() {
$scope.userResource = ApiService.getUserInformationAsResource({'username': username}).get(function(user) {
$scope.context.viewuser = user;
+ $scope.viewuser = user;
// Load the repositories.
$timeout(function() {
diff --git a/static/js/services/create-service.js b/static/js/services/create-service.js
deleted file mode 100644
index d52d3cf92..000000000
--- a/static/js/services/create-service.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * Service which exposes various methods for creating entities on the backend.
- */
-angular.module('quay').factory('CreateService', ['ApiService', 'UserService', function(ApiService, UserService) {
- var createService = {};
-
- createService.createRobotAccount = function(ApiService, is_org, orgname, name, callback) {
- ApiService.createRobot(is_org ? orgname : null, null, {'robot_shortname': name})
- .then(callback, ApiService.errorDisplay('Cannot create robot account'));
- };
-
- createService.createOrganizationTeam = function(ApiService, orgname, teamname, callback) {
- var data = {
- 'name': teamname,
- 'role': 'member'
- };
-
- var params = {
- 'orgname': orgname,
- 'teamname': teamname
- };
-
- ApiService.updateOrganizationTeam(data, params)
- .then(callback, ApiService.errorDisplay('Cannot create team'));
- };
-
- createService.askCreateRobot = function(namespace, callback) {
- if (!namespace || !UserService.isNamespaceAdmin(namespace)) { return; }
-
- var isorg = UserService.isOrganization(namespace);
- bootbox.prompt('Enter the name of the new robot account', function(robotname) {
- if (!robotname) { return; }
-
- var regex = new RegExp(ROBOT_PATTERN);
- if (!regex.test(robotname)) {
- bootbox.alert('Invalid robot account name');
- return;
- }
-
- createService.createRobotAccount(ApiService, isorg, namespace, robotname, callback);
- });
- };
-
- createService.askCreateTeam = function(namespace, callback) {
- if (!namespace || !UserService.isNamespaceAdmin(namespace)) { return; }
-
- bootbox.prompt('Enter the name of the new team', function(teamname) {
- if (!teamname) { return; }
-
- var regex = new RegExp(TEAM_PATTERN);
- if (!regex.test(teamname)) {
- bootbox.alert('Invalid team name');
- return;
- }
-
- createService.createOrganizationTeam(ApiService, namespace, teamname, callback);
- });
- };
-
- return createService;
-}]);
diff --git a/static/js/services/roles-service.js b/static/js/services/roles-service.js
index bf83e0f77..2f9854d51 100644
--- a/static/js/services/roles-service.js
+++ b/static/js/services/roles-service.js
@@ -1,20 +1,57 @@
/**
* Service which defines the various role groups.
*/
-angular.module('quay').factory('RolesService', [function() {
+angular.module('quay').factory('RolesService', ['UtilService', 'Restangular', 'ApiService', function(UtilService, Restangular, ApiService) {
var roleService = {};
- roleService.repoRoles = [
+ roleService.repoRolesOrNone = [
+ { 'id': 'none', 'title': 'None', 'kind': 'default', 'description': 'No permissions on the repository' },
+
{ 'id': 'read', 'title': 'Read', 'kind': 'success', 'description': 'Can view and pull from the repository' },
{ 'id': 'write', 'title': 'Write', 'kind': 'success', 'description': 'Can view, pull and push to the repository' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary', 'description': 'Full admin access, pull and push on the repository' }
];
+ roleService.repoRoles = roleService.repoRolesOrNone.slice(1);
+
roleService.teamRoles = [
{ 'id': 'member', 'title': 'Member', 'kind': 'default', 'description': 'Inherits all permissions of the team' },
{ 'id': 'creator', 'title': 'Creator', 'kind': 'success', 'description': 'Member and can create new repositories' },
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary', 'description': 'Full admin access to the organization' }
];
+ var getPermissionEndpoint = function(repository, entityName, kind) {
+ var namespace = repository.namespace;
+ var name = repository.name;
+ var url = UtilService.getRestUrl('repository', namespace, name, 'permissions', kind, entityName);
+ return Restangular.one(url);
+ };
+
+ roleService.deleteRepositoryRole = function(repository, entityKind, entityName, callback) {
+ var errorDisplay = ApiService.errorDisplay('Cannot change permission', function(resp) {
+ callback(false);
+ });
+
+ var endpoint = getPermissionEndpoint(repository, entityName, kind);
+ endpoint.customDELETE().then(function() {
+ callback(true);
+ }, errorHandler);
+ };
+
+ roleService.setRepositoryRole = function(repository, role, entityKind, entityName, callback) {
+ var errorDisplay = ApiService.errorDisplay('Cannot change permission', function(resp) {
+ callback(false);
+ });
+
+ var permission = {
+ 'role': role
+ };
+
+ var endpoint = getPermissionEndpoint(repository, entityName, entityKind);
+ endpoint.customPUT(permission).then(function(resp) {
+ callback(true, resp);
+ }, errorDisplay);
+ };
+
return roleService;
}]);
diff --git a/static/js/services/table-service.js b/static/js/services/table-service.js
index 08fbf9d8d..37a2a4e8e 100644
--- a/static/js/services/table-service.js
+++ b/static/js/services/table-service.js
@@ -22,6 +22,14 @@ angular.module('quay').factory('TableService', ['AngularViewArray', function(Ang
options.predicate = predicate;
};
+ tableService.getReversedTimestamp = function(datetime) {
+ if (!datetime) {
+ return -Number.MAX_VALUE;
+ }
+
+ return (new Date(datetime)).valueOf() * (-1);
+ };
+
tableService.buildOrderedItems = function(items, options, filterFields, numericFields, opt_extrafilter) {
var orderedItems = AngularViewArray.create();
diff --git a/static/js/services/ui-service.js b/static/js/services/ui-service.js
index 5bf0726dc..126a1c216 100644
--- a/static/js/services/ui-service.js
+++ b/static/js/services/ui-service.js
@@ -82,7 +82,7 @@ angular.module('quay').factory('UIService', ['$timeout', '$rootScope', '$locatio
CheckStateController.prototype.rebuildCheckedList_ = function() {
var that = this;
this.checked = [];
- this.items.forEach(function(item) {
+ this.allItems_.forEach(function(item) {
if (that.allCheckedMap_[item[that.itemKey_]]) {
that.checked.push(item);
}
diff --git a/static/js/services/user-service.js b/static/js/services/user-service.js
index ca693b74a..85612b188 100644
--- a/static/js/services/user-service.js
+++ b/static/js/services/user-service.js
@@ -134,6 +134,19 @@ function(ApiService, CookieService, $rootScope, Config) {
return !!org;
};
+ userService.getNamespace = function(namespace) {
+ var org = userService.getOrganization(namespace);
+ if (org) {
+ return org;
+ }
+
+ if (namespace == userResponse.username) {
+ return userResponse;
+ }
+
+ return null;
+ };
+
userService.currentUser = function() {
return userResponse;
};