Add collaborators view to teams manager

Adds a view of an organization's outside collaborators to the team
manager interface.
This commit is contained in:
Brad Ison 2018-03-14 11:22:21 -04:00
parent e8429f9194
commit 452379c603
No known key found for this signature in database
GPG key ID: 972D14B0BE6DE287
2 changed files with 99 additions and 42 deletions

View file

@ -12,19 +12,23 @@
<div class="tab-header-controls hidden-xs"> <div class="tab-header-controls hidden-xs">
<div class="btn-group btn-group-sm" ng-show="organization.is_admin"> <div class="btn-group btn-group-sm" ng-show="organization.is_admin">
<button class="btn" <button class="btn"
ng-class="!showingMembers ? 'btn-primary active' : 'btn-default'" ng-click="showMembers(false)"> ng-class="activeView == views.TEAMS ? 'btn-primary active' : 'btn-default'" ng-click="setActiveView(views.TEAMS)">
<i class="fa fa-group"></i>Teams View <i class="fa fa-group"></i>Teams View
</button> </button>
<button class="btn" <button class="btn"
ng-class="showingMembers ? 'btn-info active' : 'btn-default'" ng-click="showMembers(true)"> ng-class="activeView == views.MEMBERS ? 'btn-info active' : 'btn-default'" ng-click="setActiveView(views.MEMBERS)">
<i class="fa fa-user"></i>Members View <i class="fa fa-user"></i>Members View
</button> </button>
<button class="btn"
ng-class="activeView == views.COLLABORATORS ? 'btn-info active' : 'btn-default'" ng-click="setActiveView(views.COLLABORATORS)">
<i class="fa fa-user-circle"></i>Collaborators View
</button>
</div> </div>
</div> </div>
</div> </div>
<!-- Teams List --> <!-- Teams List -->
<div ng-show="!showingMembers"> <div ng-show="activeView == views.TEAMS">
<button class="btn btn-primary hidden-xs" <button class="btn btn-primary hidden-xs"
ng-show="organization.is_admin" ng-show="organization.is_admin"
style="margin-bottom: 10px; " style="margin-bottom: 10px; "
@ -127,35 +131,35 @@
</div> </div>
</div> </div>
<!-- Members List --> <!-- Members or Collaborators List -->
<div ng-show="showingMembers"> <div ng-show="activeView == views.MEMBERS || activeView == views.COLLABORATORS">
<div class="cor-loader" ng-if="!fullMemberList"></div> <div class="cor-loader" ng-if="!usersView"></div>
<div class="filter-box" collection="fullMemberList" filter-model="memberFilter" <div class="filter-box" collection="usersView" filter-model="userFilter"
filter-name="Organization Members"></div> filter-name="Users"></div>
<div class="empty" ng-if="fullMemberList.length && !(fullMemberList | filter:memberFilter).length"> <div class="empty" ng-if="usersView.length && !(usersView | filter:userFilter).length">
<div class="empty-primary-msg">No organization members found matching filter.</div> <div class="empty-primary-msg">No users found matching filter.</div>
<div class="empty-secondary-msg"> <div class="empty-secondary-msg">
Please change your filter to display members. Please change your filter to display users.
</div> </div>
</div> </div>
<table class="cor-table" ng-if="(fullMemberList | filter:memberFilter).length"> <table class="cor-table">
<thead> <thead>
<td>Member Name</td> <td>User Name</td>
<td>Teams</td> <td ng-if="activeView == views.MEMBERS">Teams</td>
<td>Direct Repository Permissions</td> <td>Direct Repository Permissions</td>
<td class="options-col"></td> <td class="options-col"></td>
</thead> </thead>
<tbody ng-repeat="memberInfo in fullMemberList | filter:memberFilter | orderBy:'name'" bindonce> <tbody ng-repeat="orgUser in usersView | filter:userFilter | orderBy:'name'" bindonce>
<tr> <tr>
<td> <td>
<div class="entity-reference" entity="memberInfo"></div> <div class="entity-reference" entity="orgUser"></div>
</td> </td>
<td> <td ng-if="activeView == views.MEMBERS">
<span ng-repeat="team in memberInfo.teams" <span ng-repeat="team in orgUser.teams"
data-title="Team {{ team.name }}" bs-tooltip> data-title="Team {{ team.name }}" bs-tooltip>
<span class="anchor" href="/organization/{{ organization.name }}/teams/{{ team.name }}"> <span class="anchor" href="/organization/{{ organization.name }}/teams/{{ team.name }}">
<span class="avatar" size="24" data="team.avatar"></span> <span class="avatar" size="24" data="team.avatar"></span>
@ -163,20 +167,20 @@
</span> </span>
</td> </td>
<td> <td>
<span class="empty" bo-if="memberInfo.repositories.length == 0"> <span class="empty" bo-if="orgUser.repositories.length == 0">
(No direct permissions on any repositories) (No direct permissions on any repositories)
</span> </span>
<span class="member-perm-summary" bo-if="memberInfo.repositories.length > 0"> <span class="member-perm-summary" bo-if="orgUser.repositories.length > 0">
Direct permissions on {{ memberInfo.repositories.length }} Direct permissions on {{ orgUser.repositories.length }}
<span bo-if="memberInfo.repositories.length == 1">repository</span> <span bo-if="orgUser.repositories.length == 1">repository</span>
<span bo-if="memberInfo.repositories.length > 1">repositories</span> <span bo-if="orgUser.repositories.length > 1">repositories</span>
under this organization under this organization
</span> </span>
</td> </td>
<td class="options-col"> <td class="options-col">
<span class="cor-options-menu" ng-if="memberInfo.name != user.username"> <span class="cor-options-menu" ng-if="orgUser.name != user.username">
<span class="cor-option" option-click="askRemoveMember(memberInfo)"> <span class="cor-option" option-click="askRemoveMember(orgUser)">
<i class="fa fa-times"></i> Remove From Organization <i class="fa fa-times"></i> Remove From Organization
</span> </span>
</span> </span>
@ -197,8 +201,8 @@
<div class="cor-confirm-dialog" <div class="cor-confirm-dialog"
dialog-context="removeMemberInfo" dialog-context="removeMemberInfo"
dialog-action="removeMember(info, callback)" dialog-action="removeMember(info, callback)"
dialog-title="Remove Organization Member" dialog-title="Remove User from Organization"
dialog-action-title="Remove Member"> dialog-action-title="Remove">
<div class="co-alert co-alert-info" style="margin-bottom: 10px;"> <div class="co-alert co-alert-info" style="margin-bottom: 10px;">
<span class="entity-reference" entity="removeMemberInfo"></span> will be removed from all teams and repositories under this organization in which they are a <span class="entity-reference" entity="removeMemberInfo"></span> will be removed from all teams and repositories under this organization in which they are a
member or have permissions. member or have permissions.

View file

@ -17,6 +17,12 @@ angular.module('quay').directive('teamsManager', function () {
$scope.Config = Config; $scope.Config = Config;
$scope.Features = Features; $scope.Features = Features;
$scope.views = Object.freeze({
TEAMS: 0,
MEMBERS: 1,
COLLABORATORS: 2
});
$scope.options = { $scope.options = {
'predicate': 'ordered_team_index', 'predicate': 'ordered_team_index',
'reverse': false, 'reverse': false,
@ -35,8 +41,11 @@ angular.module('quay').directive('teamsManager', function () {
$scope.orderedTeams = null; $scope.orderedTeams = null;
$scope.showingMembers = false; $scope.showingMembers = false;
$scope.fullMemberList = null; $scope.fullMemberList = null;
$scope.collaboratorList = null;
$scope.userView = null;
$scope.feedback = null; $scope.feedback = null;
$scope.createTeamInfo = null; $scope.createTeamInfo = null;
$scope.activeView = $scope.views.TEAMS;
var getRoleIndex = function(name) { var getRoleIndex = function(name) {
for (var i = 0; i < $scope.teamRoles.length; ++i) { for (var i = 0; i < $scope.teamRoles.length; ++i) {
@ -67,6 +76,62 @@ angular.module('quay').directive('teamsManager', function () {
['ordered_team_index', 'member_count', 'repo_count', 'role_index']); ['ordered_team_index', 'member_count', 'repo_count', 'role_index']);
}; };
var loadMembers = function(callback) {
var params = {
'orgname': $scope.organization.name
};
ApiService.getOrganizationMembers(null, params).then(function(resp) {
$scope.fullMemberList = resp['members'];
callback();
}, ApiService.errorDisplay('Could not load full membership list'));
};
var loadCollaborators = function(callback) {
var params = {
'orgname': $scope.organization.name
};
ApiService.getOrganizationCollaborators(null, params).then(function(resp) {
$scope.collaboratorList = resp['collaborators'];
callback();
}, ApiService.errorDisplay('Could not load collaborators list'));
};
$scope.setActiveView = function(view) {
switch(view) {
case $scope.views.TEAMS:
// Nothing to do here.
break;
case $scope.views.MEMBERS:
if (!$scope.fullMemberList) {
loadMembers(function() {
$scope.usersView = $scope.fullMemberList;
});
}
$scope.usersView = $scope.fullMemberList;
break;
case $scope.views.COLLABORATORS:
if (!$scope.collaboratorList) {
loadCollaborators(function() {
$scope.usersView = $scope.collaboratorList;
});
}
$scope.usersView = $scope.collaboratorList;
break;
default:
console.error('Invalid team-manager view: ' + view);
return;
}
$scope.activeView = view;
}
$scope.setRole = function(role, teamname) { $scope.setRole = function(role, teamname) {
var previousRole = $scope.organization.teams[teamname].role; var previousRole = $scope.organization.teams[teamname].role;
$scope.organization.teams[teamname].role = role; $scope.organization.teams[teamname].role = role;
@ -158,19 +223,6 @@ angular.module('quay').directive('teamsManager', function () {
$location.path('/organization/' + $scope.organization.name + '/teams/' + teamName); $location.path('/organization/' + $scope.organization.name + '/teams/' + teamName);
}; };
$scope.showMembers = function(value) {
$scope.showingMembers = value;
if (value && !$scope.fullMemberList) {
var params = {
'orgname': $scope.organization.name
};
ApiService.getOrganizationMembers(null, params).then(function(resp) {
$scope.fullMemberList = resp['members'];
}, ApiService.errorDisplay('Could not load full membership list'));
}
};
$scope.removeMember = function(memberInfo, callback) { $scope.removeMember = function(memberInfo, callback) {
var params = { var params = {
'orgname': $scope.organization.name, 'orgname': $scope.organization.name,
@ -184,7 +236,8 @@ angular.module('quay').directive('teamsManager', function () {
ApiService.removeOrganizationMember(null, params).then(function(resp) { ApiService.removeOrganizationMember(null, params).then(function(resp) {
// Reset the state of the directive. // Reset the state of the directive.
$scope.fullMemberList = null; $scope.fullMemberList = null;
$scope.showMembers(true); $scope.collaboratorList = null;
$scope.setActiveView($scope.activeView);
callback(true); callback(true);