diff --git a/bower.json b/bower.json index 5b9a7a6..9f2351f 100755 --- a/bower.json +++ b/bower.json @@ -10,7 +10,6 @@ "angular-resource": "~1.4.4", "angular-ui-router": "~0.2.13", "bootstrap": "~3.3.5", - "angular-bootstrap": "0.12.x", "angular": "~1.4.4", "PACE": "https://github.com/HubSpot/pace.git#~1.0.2", "metisMenu": "~2.0.2", @@ -33,7 +32,8 @@ "moment-timezone": "~0.5.0", "ng-file-model": "https://github.com/mistralworks/ng-file-model.git#fd1889b28e279944012919574bbcaaf45c1540d6", "angular-bootstrap-multiselect": "*", - "bootstrap-ui-datetime-picker": "^2.4.0" + "bootstrap-ui-datetime-picker": "^2.4.0", + "angular-bootstrap": "^2.5.0" }, "overrides": { "bootstrap": { diff --git a/src/app/app.js b/src/app/app.js index 831dd10..d0b8817 100755 --- a/src/app/app.js +++ b/src/app/app.js @@ -75,6 +75,13 @@ angular.module('supportAdminApp', [ templateUrl: 'app/addmembers/add.html', data: { pageTitle: 'User Management' } }) + .state('index.permission_management', { + url: '/permission_management', + templateUrl: 'app/permission_management/permission_management.html', + data: { pageTitle: 'Permission Management' }, + controller: 'PermissionManagementCtrl', + controllerAs: 'ctrl', + }) .state('index.submissions', { abstract: true, url: '/submissions', diff --git a/src/app/less/custom.less b/src/app/less/custom.less index 89f8f14..ffddbda 100755 --- a/src/app/less/custom.less +++ b/src/app/less/custom.less @@ -3,4 +3,11 @@ .welcome-message { display: none; } -} \ No newline at end of file +} + +/* Permission Management - Roles */ + +.user-in-role { + display: inline-block; + margin-right: 12px; +} diff --git a/src/app/less/navigation.less b/src/app/less/navigation.less index 3e4e56f..95ce0ee 100755 --- a/src/app/less/navigation.less +++ b/src/app/less/navigation.less @@ -476,6 +476,18 @@ body.canvas-menu.mini-navbar .navbar-default .nav li a span { display: inline; } +#side-menu { + li { + span { + vertical-align: top; + } + } + .nav-label { + display: inline-block; + width: 120px; + } +} + body.canvas-menu.mini-navbar .navbar-default .nav li .profile-element a span { display: block; } diff --git a/src/app/permission_management/permission_management.controller.js b/src/app/permission_management/permission_management.controller.js new file mode 100644 index 0000000..92dcb5b --- /dev/null +++ b/src/app/permission_management/permission_management.controller.js @@ -0,0 +1,178 @@ +angular.module('supportAdminApp') +.controller('PermissionManagementCtrl', [ + '$scope', '$timeout', 'PermissionManagementService', 'UserService', + function ($scope, $timeout, PMService, UserService) { + + var vm = this; + + /* Table initialization. */ + + angular.element(document).ready(function() { + $('.footable').footable({ + addRowToggle: true + }); + }); + + $scope.$on('permissionManagement.DataUpdated', function(event) { + $timeout(function () { + $('.footable').trigger('footable_redraw'); + }, 100); + }); + + /* Role search by name. */ + + vm.searchCreateRoleText = ''; + + vm.clearRoleSearch = function() { + vm.searchCreateRoleText = ''; + vm.searchRole(); + } + + vm.searchRole = function() { + $('.footable').trigger('footable_filter', { + filter: vm.searchCreateRoleText, + }); + } + + /* Role creation. */ + + vm.creatingNewRole = false; + vm.createNewRoleError = ''; + + vm.createNewRole = function() { + vm.creatingNewRole = true; + vm.createNewRoleError = ''; + PMService.createRole(vm.searchCreateRoleText) + .then(function(res) { + vm.roles.push(res); + loadUser(res.createdBy); + loadUser(res.modifiedBy); + vm.assignment[res.id] = {}; + vm.roles = vm.roles.sort(function(a, b) { + return a.roleName.localeCompare(b.roleName); + }); + }, function(error) { + vm.createNewRoleError = + 'Error: ' + (error.message || 'Failed to create role!'); + }).then(function() { + vm.creatingNewRole = false; + $scope.$broadcast('permissionManagement.DataUpdated'); + }); + } + + /* Role assignments. */ + + vm.assignment = {}; + + /** + * Assigns role to the user. + * @param {String} roleId + * @param {String} userHandle + */ + vm.assignRole = function(roleId, userHandle) { + vm.assignment[roleId].inProgress = true; + vm.assignment[roleId].error = ''; + vm.assignment[roleId].info = ''; + var userId; + UserService.find({ + filter: 'handle=' + userHandle, + }).then(function(res) { + if (!res.length) throw new Error('No user found!'); + userId = res[0].id; + vm.users[userId] = userHandle; + return PMService.assignRole(roleId, userId); + }).then(function() { + var role = vm.roles.find(function (r) { return r.id === roleId; }); + vm.assignment[roleId].info = + 'Success: Role ' + role.roleName + + ' assigned to the user ' + userHandle; + }, function(error) { + vm.assignment[roleId].error = + 'Error: ' + (error.message || 'Failed to assign role!'); + }).then(function() { + vm.assignment[roleId].inProgress = false; + }); + } + + /** + * Unassign role from the user. + * @param {String} roleId + * @param {String} userId + */ + vm.unassignRole = function(roleId, userHandle) { + vm.assignment[roleId].error = ''; + var role = vm.roles.find(function(r) { + return r.id === roleId; + }); + vm.assignment[roleId].error = ''; + vm.assignment[roleId].info = ''; + var userId; + UserService.find({ + filter: 'handle=' + userHandle, + }).then(function (res) { + if (!res.length) throw new Error('No user found!'); + userId = res[0].id; + vm.users[userId] = userHandle; + if (confirm('Unassign role ' + role.roleName + ' from user ' + vm.users[userId] + '?')) { + return PMService.unassignRole(roleId, userId).then(function() { + var role = vm.roles.find(function (r) { return r.id === roleId; }); + vm.assignment[roleId].info = + 'Success: Role ' + role.roleName + + ' unassigned from the user ' + userHandle; + }); + } + }).catch(function(error) { + vm.assignment[roleId].error = + 'Error: ' + (error.message || 'Failed to unassign role!'); + }); + }; + + /* Loading roles. */ + + vm.loadingRoles = true; + vm.loadingRolesError = null; + PMService.getRoles().then(function(roles) { + vm.roles = roles; + roles.forEach(function(role) { + vm.assignment[role.id] = {}; + loadUser(role.createdBy); + loadUser(role.modifiedBy); + }); + }, function(error) { + vm.loadingRolesError = + 'Error: ' + (error.message || 'Failed to load roles!'); + }).then(function() { + vm.loadingRoles = false; + $scope.$broadcast('permissionManagement.DataUpdated'); + }); + + /* Maps user ids, present in the page, into user handles. */ + vm.users = {}; + + /** + * Loads handle of the user specified by id into $scope.users. Does nothing, + * if the handle is already in there. To avoid overflooding API with + * requests, this function handles the calls sequentially. + * @param {String} id User ID. + */ + var loadingUser = false; + var userLoadQueue = []; + function loadUser(id) { + if (id && !vm.users[id]) { + if (loadingUser) userLoadQueue.push(id); + else { + loadingUser = true; + UserService.findById(id).then(function(res) { + vm.users[id] = res.handle; + loadingUser = false; + while (userLoadQueue.length) { + var next = userLoadQueue[0]; + userLoadQueue = userLoadQueue.slice(1); + if (!vm.users[next]) return loadUser(next); + } + }); + } + } + } + } +]); \ No newline at end of file diff --git a/src/app/permission_management/permission_management.html b/src/app/permission_management/permission_management.html new file mode 100644 index 0000000..9bb00bf --- /dev/null +++ b/src/app/permission_management/permission_management.html @@ -0,0 +1,191 @@ +

Press on a role row to assign/unassign users.
+| Role ID | +Role Name | +Created by | +Created at | +Modified by | +Modified at | +User handle | +
|---|---|---|---|---|---|---|
| {{role.id}} | +{{role.roleName}} | ++ + {{ctrl.users[role.createdBy]}} + + loading... + | +{{role.createdAt | date : 'MM dd yyyy HH:mm' : 'EDT'}} EDT | ++ + {{ctrl.users[role.modifiedBy]}} + + loading... + | +{{role.modifiedAt | date : 'MM dd yyyy HH:mm' : 'EDT'}} EDT | +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ctrl.assignment[role.id].error}}
+
+
+ {{ctrl.assignment[role.id].info}}
+ |
+
|
+ |
+ ||||||