Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 35 additions & 8 deletions src/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,6 @@ angular.module('supportAdminApp', [
data: { pageTitle: 'User Management' },
resolve: { auth: authenticate }
})
.state('index.permission_management', {
url: '/permission_management',
templateUrl: 'app/permission_management/permission_management.html',
data: { pageTitle: 'Permission Management' },
controller: 'PermissionManagementCtrl',
controllerAs: 'ctrl',
resolve: { auth: authenticate }
})
.state('index.submissions', {
abstract: true,
url: '/submissions',
Expand Down Expand Up @@ -303,6 +295,41 @@ angular.module('supportAdminApp', [
data: { pageTitle: 'Add Group Members' },
resolve: { auth: authenticate }
})
.state('index.roles', {
abstract: true,
url: '/roles',
templateUrl: 'app/roles/roles.html',
data: { pageTitle: 'Roles' },
controller: 'permissionmanagement.RolesController'
})
.state('index.roles.list', {
url: '/list',
templateUrl: 'app/roles/roles.list.html',
data: { pageTitle: 'Roles' },
controller: 'permissionmanagement.RolesListController',
controllerAs: 'ctrl',
resolve: { auth: authenticate }
})
.state('index.rolemembers', {
abstract: true,
url: '/rolemembers/:roleId',
templateUrl: 'app/rolemembers/rolemembers.html',
data: { pageTitle: 'Role Members' },
controller: 'permissionmanagement.RoleMembersController'
})
.state('index.rolemembers.list', {
url: '/list',
templateUrl: 'app/rolemembers/rolemembers.list.html',
controller: 'permissionmanagement.RoleMembersListController',
resolve: { auth: authenticate }
})
.state('index.rolemembers.new', {
url: '/new',
templateUrl: 'app/rolemembers/rolemembers.new.html',
controller: 'permissionmanagement.RoleMembersNewController',
data: { pageTitle: 'Add Role Members' },
resolve: { auth: authenticate }
})
.state('index.billingaccounts', {
abstract: true,
url: '/billingaccounts',
Expand Down
25 changes: 25 additions & 0 deletions src/app/groups/groups.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,31 @@ angular.module('supportAdminApp')
}).catch(GroupService.handleError);
};

/**
* Get a groups of the particular member
*
* @param {String} memberId member id
* @param {String} membershipType membership type: 'user' or 'group'
* @return {Promise} promise get a members group list
*/
GroupService.findByMember = function(memberId, membershipType) {
return $http({
method: 'GET',
url: GroupService.getBasePath() + '/groups/?memberId=' + memberId + '&membershipType=' + membershipType,
headers: {
"Content-Type": "application/json"
}
}).then(function (response) {
if (response && response.data && response.data.result) {
return response.data.result.content;
} else {
return $q.reject({
error : 'Cannot find data in response'
})
}
}).catch(GroupService.handleError);
};

/**
* Handle API response error
*
Expand Down
19 changes: 19 additions & 0 deletions src/app/rolemembers/rolemembers.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

var module = angular.module('supportAdminApp');

/**
* The parent controller for the rolemembers states
*/
module.controller('permissionmanagement.RoleMembersController', ['$scope', 'AuthService', '$state',
function ($scope, $authService, $state) {
$scope.$state = $state;

/**
* Validate the user authentication
*/
$scope.authorized = function() {
return $authService.isLoggedIn();
};
}
]);
7 changes: 7 additions & 0 deletions src/app/rolemembers/rolemembers.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div class="row wrapper border-bottom white-bg page-heading">
<div class="col-lg-10">
<h2>{{$state.current.data.pageTitle}}</h2>
</div>
<div class="col-md-10 col-lg-12" ng-include src="'components/alert/alert.html'"></div>
</div>
<div ui-view=""></div>
196 changes: 196 additions & 0 deletions src/app/rolemembers/rolemembers.list.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
'use strict';

var module = angular.module('supportAdminApp');

module.controller('permissionmanagement.RoleMembersListController', [
'$scope', '$rootScope', 'RoleService', 'IdResolverService', '$stateParams', '$state', '$q', 'Alert', '$timeout',
function ($scope, $rootScope, RoleService, IdResolverService, $stateParams, $state, $q, $alert, $timeout) {

// true if role is loading
$scope.isLoading = false;

// true if we are removing a bulk of entries
$scope.isProcessing = false;

// list of members
$scope.members = [];

// current role object
$scope.role = null;

// true if any members were selected in the list
$scope.hasSelected = false;

// if checkbox in table header is selected
$scope.isAllSelected = false;

// keep the list of members visible on the current page
var currentPageMembers = [];

/* Maps user ids, present in the page, into user handles. */
$scope.users = {};
var loadUser = IdResolverService.getUserResolverFunction($scope.users);

/**
* Return members which are selected in the table by checkboxes
*
* @return {Array} member records
*/
function getSelectedMembers() {
// return only members selected on the current page
// to make 100% sure we never delete members we cannot see
return _.filter(currentPageMembers, { isSelected: true });
}

/**
* Get role with members list
*
* @param {String} roleId role id to get
*/
$scope.loadRole = function(roleId) {
$alert.clear();
$scope.isLoading = true;

RoleService.getRole(roleId, ['id', 'roleName', 'subjects']).then(function(role) {
$scope.role = role;
$scope.members = $scope.role.subjects.map(function(memberId) {
return {
id: memberId
}
});
// if have some members we will redraw table using footable plugin
if ($scope.members.length) {
// make sure changes to scope are applied
// and redraw footable table with current member list
$timeout(function() {
$('.footable').trigger('footable_redraw');
$scope.isLoading = false;
});
} else {
$scope.isLoading = false;
}
}).catch(function (error) {
$scope.isLoading = false;
$alert.error(error.error, $rootScope);
});
};

/**
* Checks if any member records are selected in the table
* and updates $scope.hasSelected value
*/
$scope.checkSelected = function() {
$scope.hasSelected = !!getSelectedMembers().length;
}

/**
* Toggle all selected member records of specified type
*/
$scope.toggleAll = function() {
// toggle checkboxes only for current page
currentPageMembers.forEach(function(member) { member.isSelected = $scope.isAllSelected });
}

/**
* Removes member from the current role
* After removing record from the server, it removes the record from the table
*
* @param {Object} member member record
* @return {Promise} promise to remove member
*/
$scope.removeMember = function(member) {
member.isRemoving = true;
return RoleService.unassignRole($stateParams.roleId, member.id).then(function() {
_.remove($scope.members, { id: member.id });
// we remove row of deleted member from footable table
// which will also triggers footable table redraw
// we don't worry to call it after $scope.members is updated so we don't use $timeout here
var $footable = $('.footable');
var ft = $footable.data('footable');
ft.removeRow($footable.find('tr#' + member.id));
}).catch(function(error) {
member.isRemoving = false;
$alert.error('Cannot remove member with id `' + member.memberId + '`. ' + error.error, $rootScope);
});
}

/**
* Remove all selected member records
*/
$scope.removeSelected = function() {
$alert.clear();
$scope.isProcessing = true;

var selectedMembers = getSelectedMembers();

// for now we remove all members in parallel
// it's preferable, because it's faster
// though if there will be any issues with server overload
// it can be rewritten so requests go one by one
$q.all(selectedMembers.map(function(member) {
return $scope.removeMember(member);
})).then(function() {
// uncheck select all checkbox as we already removed all selected items
$scope.isAllSelected = false;
$scope.checkSelected();
}).catch(function(error) {
$alert.error(error.error, $rootScope);
}).finally(function() {
$scope.isProcessing = false;
});
}

/**
* Uncheck all checkboxes
*/
function uncheckAll() {
$scope.isAllSelected = false;
$scope.members.forEach(function(member) {
member.isSelected = false;
});
$scope.checkSelected();
}

/**
* Updates current page member list
*
* @param {Event} event event which contains ft property
*/
function updateCurrentPage(event) {
var ft = event.ft;

// if pager plugin of footable plugin was completely initialized
if (ft.pageInfo && ft.pageInfo.pages && ft.pageInfo.pages.length) {
// get the list of member on the current page
currentPageMembers = ft.pageInfo.pages[ft.pageInfo.currentPage].map(function(row) {
return _.find($scope.members, { id: row.id });
});
// clear queue of currently loading user handles
loadUser.clearQueue();
// load user handles for members visible on the current page
currentPageMembers.forEach(function(member) {
loadUser(member.id);
});
}
}

angular.element(document).ready(function() {
$('.footable').on({
// we watch footable jquery plugin footable_page_filled event
// to update current page member list when rows on the page are changed
footable_page_filled: updateCurrentPage,
// when changing sort order or page, we uncheck all checkboxes
// to avoid having checked but invisible rows
footable_paging: function() {
$scope.$apply(uncheckAll);
},
footable_sorted: function() {
$scope.$apply(uncheckAll);
}
}).footable();
});

// load role on init
$scope.loadRole($stateParams.roleId);
}
]);
70 changes: 70 additions & 0 deletions src/app/rolemembers/rolemembers.list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<div class="wrapper wrapper-content animated fadeInRight" ng-show="authorized()">
<!-- add member button row -->
<div class="row">
<div class="col col-md-12 col-lg-12">
<a class="btn btn-primary pull-right m-b" ui-sref="index.roles.list" style="margin-left: 20px">
<strong>Back</strong>
</a>
<a class="btn btn-info pull-right m-b" ui-sref="index.rolemembers.new({roleId: role.id})">
<strong><i class="fa fa-plus"></i> Add Members</strong>
</a>
</div>
</div>
<!-- list members row -->
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h2>
<span ng-if="role">{{role.roleName}}</span>
<span class="text-info" ng-if="!role">loading...</span>
</h2>
</div>
<div class="ibox-content">
<div class="text-center" ng-show="isLoading">
<img src="assets/images/loading.gif" />
</div>
<div ng-show="!isLoading">
<table class="footable table table-stripped toggle-arrow-tiny" ng-show="members.length" data-page-size="20">
<thead>
<tr>
<th data-sort-ignore="true"><input type="checkbox" ng-model="isAllSelected" ng-change="toggleAll(); checkSelected();" /></th>
<th data-type="numeric">User Id</th>
<th>Handle</th>
<th data-sort-ignore="true">&nbsp;</th>
</tr>
</thead>

<tbody>
<tr class="animate-repeat" ng-repeat="member in members" id="{{member.id}}">
<td><input type="checkbox" ng-model="member.isSelected" ng-change="checkSelected();" /></td>
<td>{{member.id}}</td>
<td>
<span ng-if="users[member.id]">{{users[member.id]}}</span>
<span class="text-info" ng-if="member.id && !users[member.id]">loading...</span>
</td>
<td>
<button data-ng-click='removeMember(member)' class="btn btn-sm btn-danger" ng-disabled="member.isRemoving">
<strong>Remove</strong>
</button>
</td>
</tr>
</tbody>

<tfoot>
<tr>
<td colspan="4">
<ul class="pagination pull-right"></ul>
</td>
</tr>
</tfoot>
</table>
<div ng-show="!members.length">No members</div><br/>

<button data-ng-click='removeSelected()' class="btn btn-sm btn-danger" ng-disabled="!hasSelected || isProcessing" ng-show="members.length"><strong>Remove Selected</strong></button>
</div>
</div>
</div>
</div>
</div>
</div>
Loading