Start on new org view
This commit is contained in:
parent
a7a8571396
commit
2459b6b467
11 changed files with 442 additions and 103 deletions
|
@ -24,16 +24,20 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def org_view(o, teams):
|
def org_view(o, teams):
|
||||||
admin_org = AdministerOrganizationPermission(o.username)
|
is_admin = AdministerOrganizationPermission(o.username).can()
|
||||||
is_admin = admin_org.can()
|
is_member = OrganizationMemberPermission(o.username).can()
|
||||||
|
|
||||||
view = {
|
view = {
|
||||||
'name': o.username,
|
'name': o.username,
|
||||||
'email': o.email if is_admin else '',
|
'email': o.email if is_admin else '',
|
||||||
'avatar': avatar.compute_hash(o.email, name=o.username),
|
'avatar': avatar.compute_hash(o.email, name=o.username),
|
||||||
'teams': {t.name : team_view(o.username, t) for t in teams},
|
'is_admin': is_admin,
|
||||||
'is_admin': is_admin
|
'is_member': is_member
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if teams is not None:
|
||||||
|
view['teams'] = {t.name : team_view(o.username, t) for t in teams}
|
||||||
|
|
||||||
if is_admin:
|
if is_admin:
|
||||||
view['invoice_email'] = o.invoice_email
|
view['invoice_email'] = o.invoice_email
|
||||||
|
|
||||||
|
@ -129,17 +133,17 @@ class Organization(ApiResource):
|
||||||
@nickname('getOrganization')
|
@nickname('getOrganization')
|
||||||
def get(self, orgname):
|
def get(self, orgname):
|
||||||
""" Get the details for the specified organization """
|
""" Get the details for the specified organization """
|
||||||
permission = OrganizationMemberPermission(orgname)
|
try:
|
||||||
if permission.can():
|
org = model.get_organization(orgname)
|
||||||
try:
|
except model.InvalidOrganizationException:
|
||||||
org = model.get_organization(orgname)
|
raise NotFound()
|
||||||
except model.InvalidOrganizationException:
|
|
||||||
raise NotFound()
|
|
||||||
|
|
||||||
|
teams = None
|
||||||
|
if OrganizationMemberPermission(orgname).can():
|
||||||
teams = model.get_teams_within_org(org)
|
teams = model.get_teams_within_org(org)
|
||||||
return org_view(org, teams)
|
|
||||||
|
|
||||||
raise Unauthorized()
|
return org_view(org, teams)
|
||||||
|
|
||||||
|
|
||||||
@require_scope(scopes.ORG_ADMIN)
|
@require_scope(scopes.ORG_ADMIN)
|
||||||
@nickname('changeOrganizationDetails')
|
@nickname('changeOrganizationDetails')
|
||||||
|
|
9
static/css/pages/org-view.css
Normal file
9
static/css/pages/org-view.css
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.org-view .organization-name {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.org-view h3 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
|
@ -2,15 +2,17 @@
|
||||||
<div class="new-repo-listing">
|
<div class="new-repo-listing">
|
||||||
|
|
||||||
<!-- Titles -->
|
<!-- Titles -->
|
||||||
<div ng-if="starred" class="repo-list-title">
|
<div ng-if="!hideTitle">
|
||||||
<i class="fa fa-star starred"></i>
|
<div ng-if="starred" class="repo-list-title">
|
||||||
Starred
|
<i class="fa fa-star starred"></i>
|
||||||
</div>
|
Starred
|
||||||
<div ng-if="!starred" class="repo-list-title">
|
</div>
|
||||||
<span class="avatar" size="24" hash="namespace.avatar"></span>
|
<div ng-if="!starred" class="repo-list-title">
|
||||||
<span ng-if="!isOrganization(namespace.name)">{{ namespace.name }}</span>
|
<span class="avatar" size="24" hash="namespace.avatar"></span>
|
||||||
<a ng-if="isOrganization(namespace.name)"
|
<span ng-if="!isOrganization(namespace.name)">{{ namespace.name }}</span>
|
||||||
href="/organization/{{ namespace.name }}">{{ namespace.name }}</a>
|
<a ng-if="isOrganization(namespace.name)"
|
||||||
|
href="/organization/{{ namespace.name }}">{{ namespace.name }}</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Repositories -->
|
<!-- Repositories -->
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
error-message="'Could not load repository events'">
|
error-message="'Could not load repository events'">
|
||||||
|
|
||||||
<div class="empty" ng-if="!notifications.length">
|
<div class="empty" ng-if="!notifications.length">
|
||||||
<div class="empty-primary-msg">No notification have been setup for this repository.</div>
|
<div class="empty-primary-msg">No notifications have been setup for this repository.</div>
|
||||||
<div class="empty-secondary-msg" ng-if="repository.can_write">
|
<div class="empty-secondary-msg" ng-if="repository.can_write">
|
||||||
Click the "Create Notification" button above to add a new notification for a repository event.
|
Click the "Create Notification" button above to add a new notification for a repository event.
|
||||||
</div>
|
</div>
|
||||||
|
|
30
static/directives/teams-manager.html
Normal file
30
static/directives/teams-manager.html
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<div class="teams-manager-element">
|
||||||
|
<span class="popup-input-button" pattern="TEAM_PATTERN" placeholder="'Team Name'"
|
||||||
|
submitted="createTeam(value)">
|
||||||
|
<i class="fa fa-group"></i> Create Team
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="team-listing" ng-repeat="(name, team) in organization.teams">
|
||||||
|
<div id="team-{{name}}" class="row">
|
||||||
|
<div class="col-sm-7 col-md-8">
|
||||||
|
<div class="team-title">
|
||||||
|
<i class="fa fa-group"></i>
|
||||||
|
<span ng-show="team.can_view">
|
||||||
|
<a href="/organization/{{ organization.name }}/teams/{{ team.name }}">{{ team.name }}</a>
|
||||||
|
</span>
|
||||||
|
<span ng-show="!team.can_view">
|
||||||
|
{{ team.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="team-description markdown-view" content="team.description" first-line-only="true"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-5 col-md-4 control-col" ng-show="organization.is_admin">
|
||||||
|
<span class="role-group" current-role="team.role" role-changed="setRole(role, team.name)" roles="teamRoles"></span>
|
||||||
|
<button class="btn btn-sm btn-danger" ng-click="askDeleteTeam(team.name)">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -11,9 +11,9 @@ angular.module('quay').directive('repoListGrid', function () {
|
||||||
scope: {
|
scope: {
|
||||||
repositoriesResource: '=repositoriesResource',
|
repositoriesResource: '=repositoriesResource',
|
||||||
starred: '=starred',
|
starred: '=starred',
|
||||||
user: "=user",
|
|
||||||
namespace: '=namespace',
|
namespace: '=namespace',
|
||||||
starToggled: '&starToggled'
|
starToggled: '&starToggled',
|
||||||
|
hideTitle: '=hideTitle'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element, UserService) {
|
controller: function($scope, $element, UserService) {
|
||||||
$scope.isOrganization = function(namespace) {
|
$scope.isOrganization = function(namespace) {
|
||||||
|
|
82
static/js/directives/ui/teams-manager.js
Normal file
82
static/js/directives/ui/teams-manager.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/**
|
||||||
|
* Element for managing the teams of an organization.
|
||||||
|
*/
|
||||||
|
angular.module('quay').directive('teamsManager', function () {
|
||||||
|
var directiveDefinitionObject = {
|
||||||
|
priority: 0,
|
||||||
|
templateUrl: '/static/directives/teams-manager.html',
|
||||||
|
replace: false,
|
||||||
|
transclude: false,
|
||||||
|
restrict: 'C',
|
||||||
|
scope: {
|
||||||
|
'organization': '=organization'
|
||||||
|
},
|
||||||
|
controller: function($scope, $element, ApiService, CreateService) {
|
||||||
|
$scope.TEAM_PATTERN = TEAM_PATTERN;
|
||||||
|
$scope.teamRoles = [
|
||||||
|
{ 'id': 'member', 'title': 'Member', 'kind': 'default' },
|
||||||
|
{ 'id': 'creator', 'title': 'Creator', 'kind': 'success' },
|
||||||
|
{ 'id': 'admin', 'title': 'Admin', 'kind': 'primary' }
|
||||||
|
];
|
||||||
|
|
||||||
|
$scope.setRole = function(role, teamname) {
|
||||||
|
var previousRole = $scope.organization.teams[teamname].role;
|
||||||
|
$scope.organization.teams[teamname].role = role;
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
'orgname': $scope.organization.name,
|
||||||
|
'teamname': teamname
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = $scope.organization.teams[teamname];
|
||||||
|
|
||||||
|
var errorHandler = ApiService.errorDisplay('Cannot update team', function(resp) {
|
||||||
|
$scope.organization.teams[teamname].role = previousRole;
|
||||||
|
});
|
||||||
|
|
||||||
|
ApiService.updateOrganizationTeam(data, params).then(function(resp) {
|
||||||
|
}, errorHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.createTeam = function(teamname) {
|
||||||
|
if (!teamname) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scope.organization.teams[teamname]) {
|
||||||
|
$('#team-' + teamname).removeClass('highlight');
|
||||||
|
setTimeout(function() {
|
||||||
|
$('#team-' + teamname).addClass('highlight');
|
||||||
|
}, 10);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var orgname = $scope.organization.name;
|
||||||
|
CreateService.createOrganizationTeam(ApiService, orgname, teamname, function(created) {
|
||||||
|
$scope.organization.teams[teamname] = created;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.askDeleteTeam = function(teamname) {
|
||||||
|
bootbox.confirm('Are you sure you want to delete team ' + teamname + '?', function(resp) {
|
||||||
|
if (resp) {
|
||||||
|
$scope.deleteTeam(teamname);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.deleteTeam = function(teamname) {
|
||||||
|
var params = {
|
||||||
|
'orgname': $scope.organization.name,
|
||||||
|
'teamname': teamname
|
||||||
|
};
|
||||||
|
|
||||||
|
ApiService.deleteOrganizationTeam(null, params).then(function() {
|
||||||
|
delete $scope.organization.teams[teamname];
|
||||||
|
}, ApiService.errorDisplay('Cannot delete team'));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return directiveDefinitionObject;
|
||||||
|
});
|
|
@ -1,6 +1,6 @@
|
||||||
(function() {
|
(function() {
|
||||||
/**
|
/**
|
||||||
* Organization admin/settings page.
|
* DEPRECATED: Organization admin/settings page.
|
||||||
*/
|
*/
|
||||||
angular.module('quayPages').config(['pages', function(pages) {
|
angular.module('quayPages').config(['pages', function(pages) {
|
||||||
pages.create('org-admin', 'org-admin.html', OrgAdminCtrl);
|
pages.create('org-admin', 'org-admin.html', OrgAdminCtrl);
|
||||||
|
|
|
@ -3,10 +3,94 @@
|
||||||
* Page that displays details about an organization, such as its teams.
|
* Page that displays details about an organization, such as its teams.
|
||||||
*/
|
*/
|
||||||
angular.module('quayPages').config(['pages', function(pages) {
|
angular.module('quayPages').config(['pages', function(pages) {
|
||||||
pages.create('org-view', 'org-view.html', OrgViewCtrl);
|
pages.create('org-view', 'org-view.html', OrgViewCtrl, {
|
||||||
|
'newLayout': true,
|
||||||
|
'title': 'Organization {{ organization.name }}',
|
||||||
|
'description': 'Organization {{ organization.name }}'
|
||||||
|
}, ['layout'])
|
||||||
|
|
||||||
|
pages.create('org-view', 'old-org-view.html', OldOrgViewCtrl, {
|
||||||
|
}, ['old-layout']);
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
function OrgViewCtrl($rootScope, $scope, ApiService, $routeParams, CreateService) {
|
function OrgViewCtrl($scope, $routeParams, $timeout, ApiService, UIService) {
|
||||||
|
var orgname = $routeParams.orgname;
|
||||||
|
|
||||||
|
$scope.showLogsCounter = 0;
|
||||||
|
$scope.showApplicationsCounter = 0;
|
||||||
|
$scope.showInvoicesCounter = 0;
|
||||||
|
$scope.changingOrganization = false;
|
||||||
|
|
||||||
|
$scope.$watch('organizationEmail', function(e) {
|
||||||
|
UIService.hidePopover('#changeEmailForm');
|
||||||
|
});
|
||||||
|
|
||||||
|
var loadRepositories = function() {
|
||||||
|
var options = {
|
||||||
|
'public': false,
|
||||||
|
'private': true,
|
||||||
|
'sort': true,
|
||||||
|
'namespace': orgname,
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.repositoriesResource = ApiService.listReposAsResource().withOptions(options).get(function(resp) {
|
||||||
|
return resp.repositories;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadOrganization = function() {
|
||||||
|
$scope.orgResource = ApiService.getOrganizationAsResource({'orgname': orgname}).get(function(org) {
|
||||||
|
$scope.organization = org;
|
||||||
|
$scope.organizationEmail = org.email;
|
||||||
|
$scope.isAdmin = org.is_admin;
|
||||||
|
$scope.isMember = org.is_member;
|
||||||
|
|
||||||
|
// Load the repositories.
|
||||||
|
$timeout(function() {
|
||||||
|
loadRepositories();
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load the organization.
|
||||||
|
loadOrganization();
|
||||||
|
|
||||||
|
$scope.showInvoices = function() {
|
||||||
|
$scope.showInvoicesCounter++;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.showApplications = function() {
|
||||||
|
$scope.showApplicationsCounter++;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.showLogs = function() {
|
||||||
|
$scope.showLogsCounter++;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.changeEmail = function() {
|
||||||
|
UIService.hidePopover('#changeEmailForm');
|
||||||
|
|
||||||
|
$scope.changingOrganization = true;
|
||||||
|
var params = {
|
||||||
|
'orgname': orgname
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
'email': $scope.organizationEmail
|
||||||
|
};
|
||||||
|
|
||||||
|
ApiService.changeOrganizationDetails(data, params).then(function(org) {
|
||||||
|
$scope.changingOrganization = false;
|
||||||
|
$scope.changeEmailForm.$setPristine();
|
||||||
|
$scope.organization = org;
|
||||||
|
}, function(result) {
|
||||||
|
$scope.changingOrganization = false;
|
||||||
|
UIService.showFormError('#changeEmailForm', result);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function OldOrgViewCtrl($rootScope, $scope, ApiService, $routeParams, CreateService) {
|
||||||
var orgname = $routeParams.orgname;
|
var orgname = $routeParams.orgname;
|
||||||
|
|
||||||
$scope.TEAM_PATTERN = TEAM_PATTERN;
|
$scope.TEAM_PATTERN = TEAM_PATTERN;
|
||||||
|
|
85
static/partials/old-org-view.html
Normal file
85
static/partials/old-org-view.html
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
<div class="resource-view" resource="orgResource" error-message="'No matching organization found'">
|
||||||
|
<div class="org-view cor-container">
|
||||||
|
<div class="organization-header" organization="organization">
|
||||||
|
<div class="header-buttons" ng-show="organization.is_admin">
|
||||||
|
|
||||||
|
<span class="popup-input-button" pattern="TEAM_PATTERN" placeholder="'Team Name'"
|
||||||
|
submitted="createTeam(value)">
|
||||||
|
<i class="fa fa-group"></i> Create Team
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<a class="btn btn-default" href="/organization/{{ organization.name }}/admin"><i class="fa fa-gear"></i> Settings</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row hidden-xs">
|
||||||
|
<div class="col-md-4 col-md-offset-8 col-sm-5 col-sm-offset-7 header-col" ng-show="organization.is_admin">
|
||||||
|
Team Permissions
|
||||||
|
<i class="info-icon fa fa-info-circle" data-placement="bottom" data-original-title="" data-title=""
|
||||||
|
data-content="Global permissions for the team and its members<br><br><dl><dt>Member</dt><dd>Permissions are assigned on a per repository basis</dd><dt>Creator</dt><dd>A team can create its own repositories</dd><dt>Admin</dt><dd>A team has full control of the organization</dd></dl>"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="team-listing" ng-repeat="(name, team) in organization.teams">
|
||||||
|
<div id="team-{{name}}" class="row">
|
||||||
|
<div class="col-sm-7 col-md-8">
|
||||||
|
<div class="team-title">
|
||||||
|
<i class="fa fa-group"></i>
|
||||||
|
<span ng-show="team.can_view">
|
||||||
|
<a href="/organization/{{ organization.name }}/teams/{{ team.name }}">{{ team.name }}</a>
|
||||||
|
</span>
|
||||||
|
<span ng-show="!team.can_view">
|
||||||
|
{{ team.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="team-description markdown-view" content="team.description" first-line-only="true"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-5 col-md-4 control-col" ng-show="organization.is_admin">
|
||||||
|
<span class="role-group" current-role="team.role" role-changed="setRole(role, team.name)" roles="teamRoles"></span>
|
||||||
|
<button class="btn btn-sm btn-danger" ng-click="askDeleteTeam(team.name)">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal message dialog -->
|
||||||
|
<div class="modal fade" id="cannotChangeTeamModal">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title">Cannot change team</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<span ng-show="!roleError">You do not have permission to change properties on teams.</span>
|
||||||
|
<span ng-show="roleError">{{ roleError }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div><!-- /.modal-content -->
|
||||||
|
</div><!-- /.modal-dialog -->
|
||||||
|
</div><!-- /.modal -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Modal message dialog -->
|
||||||
|
<div class="modal fade" id="confirmdeleteModal">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title">Delete Team?</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Are you sure you would like to delete this team? This <b>cannot be undone</b>.
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger" ng-click="deleteTeam()">Delete Team</button>
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div><!-- /.modal-content -->
|
||||||
|
</div><!-- /.modal-dialog -->
|
||||||
|
</div><!-- /.modal -->
|
|
@ -1,85 +1,128 @@
|
||||||
<div class="resource-view" resource="orgResource" error-message="'No matching organization found'">
|
<div class="resource-view org-view"
|
||||||
<div class="org-view cor-container">
|
resource="orgResource"
|
||||||
<div class="organization-header" organization="organization">
|
error-message="'Organization not found'">
|
||||||
<div class="header-buttons" ng-show="organization.is_admin">
|
<div class="page-content">
|
||||||
|
<div class="cor-title">
|
||||||
|
<span class="cor-title-link"></span>
|
||||||
|
<span class="cor-title-content">
|
||||||
|
<span class="avatar" size="32" hash="organization.avatar"></span>
|
||||||
|
<span class="organization-name">{{ organization.name }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<span class="popup-input-button" pattern="TEAM_PATTERN" placeholder="'Team Name'"
|
<div class="cor-tab-panel">
|
||||||
submitted="createTeam(value)">
|
<div class="cor-tabs" quay-show="isMember">
|
||||||
<i class="fa fa-group"></i> Create Team
|
<span class="cor-tab" tab-active="true" tab-title="Repositories" tab-target="#repos">
|
||||||
|
<i class="fa fa-hdd-o"></i>
|
||||||
</span>
|
</span>
|
||||||
|
<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">
|
||||||
|
<i class="fa fa-wrench"></i>
|
||||||
|
</span>
|
||||||
|
<span class="cor-tab" tab-title="Default Permissions" tab-target="#default" ng-if="isAdmin">
|
||||||
|
<i class="fa ci-stamp"></i>
|
||||||
|
</span>
|
||||||
|
<span class="cor-tab" tab-title="Billing" tab-target="#usage"
|
||||||
|
quay-show="isAdmin && Features.BILLING">
|
||||||
|
<i class="fa fa-credit-card"></i>
|
||||||
|
</span>
|
||||||
|
<span class="cor-tab" tab-title="Billing Invoices" tab-target="#invoices"
|
||||||
|
tab-init="showInvoices()" quay-show="isAdmin && Features.BILLING">
|
||||||
|
<i class="fa ci-invoice"></i>
|
||||||
|
</span>
|
||||||
|
<span class="cor-tab" tab-title="Usage Logs" tab-target="#logs"
|
||||||
|
tab-init="showLogs()" ng-if="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">
|
||||||
|
<i class="fa ci-application"></i>
|
||||||
|
</span>
|
||||||
|
<span class="cor-tab" tab-title="Organization Settings" tab-target="#settings"
|
||||||
|
ng-if="isAdmin">
|
||||||
|
<i class="fa fa-gears"></i>
|
||||||
|
</span>
|
||||||
|
</div> <!-- /cor-tabs -->
|
||||||
|
|
||||||
<a class="btn btn-default" href="/organization/{{ organization.name }}/admin"><i class="fa fa-gear"></i> Settings</a>
|
<div class="cor-tab-content">
|
||||||
</div>
|
<!-- Repositories -->
|
||||||
</div>
|
<div id="repos" class="tab-pane active">
|
||||||
|
<h3>Repositories</h3>
|
||||||
|
<div class="repo-list-grid"
|
||||||
|
repositories-resource="repositoriesResource"
|
||||||
|
starred="false"
|
||||||
|
namespace="namespace"
|
||||||
|
hide-title="true">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row hidden-xs">
|
<!-- Teams -->
|
||||||
<div class="col-md-4 col-md-offset-8 col-sm-5 col-sm-offset-7 header-col" ng-show="organization.is_admin">
|
<div id="teams" class="tab-pane">
|
||||||
Team Permissions
|
<h3>Teams</h3>
|
||||||
<i class="info-icon fa fa-info-circle" data-placement="bottom" data-original-title="" data-title=""
|
<div class="teams-manager" organization="organization"></div>
|
||||||
data-content="Global permissions for the team and its members<br><br><dl><dt>Member</dt><dd>Permissions are assigned on a per repository basis</dd><dt>Creator</dt><dd>A team can create its own repositories</dd><dt>Admin</dt><dd>A team has full control of the organization</dd></dl>"></i>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="team-listing" ng-repeat="(name, team) in organization.teams">
|
<!-- Robot Accounts -->
|
||||||
<div id="team-{{name}}" class="row">
|
<div id="robots" class="tab-pane">
|
||||||
<div class="col-sm-7 col-md-8">
|
<h3>Robot Accounts</h3>
|
||||||
<div class="team-title">
|
<div class="robots-manager" organization="organization"></div>
|
||||||
<i class="fa fa-group"></i>
|
</div>
|
||||||
<span ng-show="team.can_view">
|
|
||||||
<a href="/organization/{{ organization.name }}/teams/{{ team.name }}">{{ team.name }}</a>
|
<!-- Default Permissions -->
|
||||||
</span>
|
<div id="default" class="tab-pane">
|
||||||
<span ng-show="!team.can_view">
|
<h3>Default Permissions</h3>
|
||||||
{{ team.name }}
|
<div class="prototype-manager" organization="organization"></div>
|
||||||
</span>
|
</div>
|
||||||
|
|
||||||
|
<!-- Usage Logs -->
|
||||||
|
<div id="logs" class="tab-pane">
|
||||||
|
<div class="logs-view" organization="organization" makevisible="showLogsCounter"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Applications -->
|
||||||
|
<div id="applications" class="tab-pane">
|
||||||
|
<h3>Applications</h3>
|
||||||
|
<div class="application-manager" organization="organization"
|
||||||
|
makevisible="showApplicationsCounter"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Plan and Usage -->
|
||||||
|
<div id="usage" class="tab-pane" quay-require="['BILLING']">
|
||||||
|
<h3>Plan Usage and Billing</h3>
|
||||||
|
<div class="plan-manager" organization="organization.name"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Billing Invoices -->
|
||||||
|
<div id="invoices" class="tab-pane" quay-require="['BILLING']">
|
||||||
|
<h3>Billing Invoices</h3>
|
||||||
|
<div class="billing-invoices" organization="organization"
|
||||||
|
makevisible="showInvoicesCounter"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Settings -->
|
||||||
|
<div id="settings" class="tab-pane">
|
||||||
|
<h3>Organization Settings</h3>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="panel" ng-show="!changingOrganization">
|
||||||
|
<div class="panel-title">Organization's e-mail address</div>
|
||||||
|
<div class="panel-content" style="padding-left: 20px; margin-top: 10px;">
|
||||||
|
<form class="form-change" id="changeEmailForm" name="changeEmailForm" ng-submit="changeEmail()" data-trigger="manual"
|
||||||
|
data-content="{{ changeEmailError }}" data-placement="bottom" ng-show="!updatingOrganization">
|
||||||
|
<span class="avatar" size="24" email="organizationEmail" name="orgname"></span>
|
||||||
|
<input type="email" class="form-control" ng-model="organizationEmail"
|
||||||
|
style="margin-left: 10px; margin-right: 10px; width: 400px; display: inline-block;" required>
|
||||||
|
<button class="btn btn-primary" type="submit" ng-disabled="changeEmailForm.$invalid || organizationEmail == organization.email">
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="team-description markdown-view" content="team.description" first-line-only="true"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div> <!-- /cor-tab-content -->
|
||||||
<div class="col-sm-5 col-md-4 control-col" ng-show="organization.is_admin">
|
|
||||||
<span class="role-group" current-role="team.role" role-changed="setRole(role, team.name)" roles="teamRoles"></span>
|
|
||||||
<button class="btn btn-sm btn-danger" ng-click="askDeleteTeam(team.name)">Delete</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal message dialog -->
|
|
||||||
<div class="modal fade" id="cannotChangeTeamModal">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
||||||
<h4 class="modal-title">Cannot change team</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<span ng-show="!roleError">You do not have permission to change properties on teams.</span>
|
|
||||||
<span ng-show="roleError">{{ roleError }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div><!-- /.modal-content -->
|
|
||||||
</div><!-- /.modal-dialog -->
|
|
||||||
</div><!-- /.modal -->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Modal message dialog -->
|
|
||||||
<div class="modal fade" id="confirmdeleteModal">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
||||||
<h4 class="modal-title">Delete Team?</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
Are you sure you would like to delete this team? This <b>cannot be undone</b>.
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-danger" ng-click="deleteTeam()">Delete Team</button>
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div><!-- /.modal-content -->
|
|
||||||
</div><!-- /.modal-dialog -->
|
|
||||||
</div><!-- /.modal -->
|
|
||||||
|
|
Reference in a new issue