diff options
| author | Yoshie Muranaka <yoshiemuranaka@gmail.com> | 2019-09-16 10:33:16 -0700 |
|---|---|---|
| committer | Yoshie Muranaka <yoshiemuranaka@gmail.com> | 2019-09-24 10:27:00 -0700 |
| commit | 49001e25fb1e1abd22e56023992a53c10b4d7055 (patch) | |
| tree | 2f7ac750f5e3bda78d4be63d785fa17d3b39169a | |
| parent | 5b8cef81cfa896ecdb0b6ad9d43c78d67d087a62 (diff) | |
| download | phosphor-webui-49001e25fb1e1abd22e56023992a53c10b4d7055.tar.gz phosphor-webui-49001e25fb1e1abd22e56023992a53c10b4d7055.zip | |
Add batch actions to local user table
Add ability to remove, enable, disable local users in bulk.
- Updates to table-actions component to fix flickering issue
by including track by $index in ng-repeat
Signed-off-by: Yoshie Muranaka <yoshiemuranaka@gmail.com>
Change-Id: I67039e9b9d9cf7debe9f6ef87e71210bd4b64251
| -rw-r--r-- | app/common/components/table/table-actions.js | 6 | ||||
| -rw-r--r-- | app/common/components/table/table.html | 1 | ||||
| -rw-r--r-- | app/common/components/table/table.js | 1 | ||||
| -rw-r--r-- | app/users/controllers/user-accounts-controller.html | 3 | ||||
| -rw-r--r-- | app/users/controllers/user-accounts-controller.js | 124 | ||||
| -rw-r--r-- | app/users/controllers/user-accounts-modal-remove.html | 3 |
6 files changed, 112 insertions, 26 deletions
diff --git a/app/common/components/table/table-actions.js b/app/common/components/table/table-actions.js index e1e47ec..d76d5e5 100644 --- a/app/common/components/table/table-actions.js +++ b/app/common/components/table/table-actions.js @@ -58,9 +58,9 @@ window.angular && (function(angular) { }; /** - * onInit Component lifecycle hook + * onChanges Component lifecycle hook */ - this.$onInit = () => { + this.$onChanges = () => { this.actions = setActions(this.actions); }; }; @@ -73,7 +73,7 @@ window.angular && (function(angular) { class="btn btn-tertiary" type="button" aria-label="{{action.type}}" - ng-repeat="action in $ctrl.actions" + ng-repeat="action in $ctrl.actions track by $index" ng-disabled="!action.enabled" ng-click="$ctrl.onClick(action.type)"> <icon ng-if="action.file !== null" ng-file="{{action.file}}"></icon> diff --git a/app/common/components/table/table.html b/app/common/components/table/table.html index 7d906a1..387b18d 100644 --- a/app/common/components/table/table.html +++ b/app/common/components/table/table.html @@ -99,6 +99,7 @@ <td ng-if="$ctrl.rowActionsEnabled" class="bmc-table__cell bmc-table__row-actions"> <table-actions + ng-if="row.actions" actions="row.actions" emit-action="$ctrl.onEmitRowAction(action, row)"> </table-actions> diff --git a/app/common/components/table/table.js b/app/common/components/table/table.js index 2063555..a382429 100644 --- a/app/common/components/table/table.js +++ b/app/common/components/table/table.js @@ -288,6 +288,7 @@ window.angular && (function(angular) { const dataChange = onChangesObj.data; if (dataChange) { prepData(); + deselectAllRows(); } }; }; diff --git a/app/users/controllers/user-accounts-controller.html b/app/users/controllers/user-accounts-controller.html index 9577196..31ba62d 100644 --- a/app/users/controllers/user-accounts-controller.html +++ b/app/users/controllers/user-accounts-controller.html @@ -26,7 +26,10 @@ data="tableData" header="tableHeader" row-actions-enabled="true" + selectable="true" + batch-actions="tableBatchActions" emit-row-action="onEmitRowAction(value)" + emit-batch-action="onEmitBatchAction(value)" class="local-users__table"> </bmc-table> </div> diff --git a/app/users/controllers/user-accounts-controller.js b/app/users/controllers/user-accounts-controller.js index 9f31beb..2e7605c 100644 --- a/app/users/controllers/user-accounts-controller.js +++ b/app/users/controllers/user-accounts-controller.js @@ -10,8 +10,8 @@ window.angular && (function(angular) { 'use strict'; angular.module('app.users').controller('userAccountsController', [ - '$scope', 'APIUtils', 'toastService', '$uibModal', - function($scope, APIUtils, toastService, $uibModal) { + '$scope', 'APIUtils', 'toastService', '$uibModal', '$q', + function($scope, APIUtils, toastService, $uibModal, $q) { $scope.loading; $scope.accountSettings; $scope.userRoles; @@ -21,6 +21,19 @@ window.angular && (function(angular) { $scope.tableHeader = [ {label: 'Username'}, {label: 'Privilege'}, {label: 'Account status'} ]; + $scope.tableBatchActions = [ + {type: 'delete', label: 'Remove'}, + {type: 'enable', label: 'Enable'}, + {type: 'disable', label: 'Disable'}, + ]; + + /** + * Returns true if username is 'root' + * @param {*} user + */ + function checkIfRoot(user) { + return user.UserName === 'root' ? true : false; + } /** * Data table mapper @@ -33,10 +46,10 @@ window.angular && (function(angular) { const editAction = {type: 'Edit', enabled: true, file: 'icon-edit.svg'}; const deleteAction = { type: 'Delete', - enabled: user.UserName === 'root' ? false : true, + enabled: checkIfRoot(user) ? false : true, file: 'icon-trashcan.svg' }; - + user.selectable = checkIfRoot(user) ? false : true; user.actions = [editAction, deleteAction]; user.uiData = [user.UserName, user.RoleId, accountStatus]; return user; @@ -144,21 +157,74 @@ window.angular && (function(angular) { } /** - * API call to delete user - * @param {*} username + * API call to delete users + * @param {*} users : Array of users to delete */ - function deleteUser(username) { + function deleteUsers(users = []) { $scope.loading = true; - APIUtils.deleteUser(username) + const promises = + users.map((user) => APIUtils.deleteUser(user.UserName)); + $q.all(promises) .then(() => { + let message; + if (users.length > 1) { + message = 'Users have been removed.' + } else { + message = `User '${users[0].UserName}' has been removed.` + } + toastService.success(message); + }) + .catch((error) => { + console.log(JSON.stringify(error)); + let message; + if (users.length > 1) { + message = 'Failed to remove users.' + } else { + message = `Failed to remove user '${users[0].UserName}'.` + } + toastService.error(message); + }) + .finally(() => { getLocalUsers(); - toastService.success(`User '${username}' has been deleted.`); + $scope.loading = false; + }); + } + + /** + * API call to update user status enabled/disabled + * @param {*} users : Array of users to update + * @param {boolean} enabled : status + */ + function updateUserStatus(users = [], enabled = true) { + $scope.loading = true; + const promises = users.map( + (user) => APIUtils.updateUser( + user.UserName, null, null, null, enabled, null)); + $q.all(promises) + .then(() => { + let message; + let statusLabel = enabled ? 'enabled' : 'disabled'; + if (users.length > 1) { + message = `Users ${statusLabel}.` + } else { + message = `User '${users[0].UserName}' ${statusLabel}.`; + } + toastService.success(message); }) .catch((error) => { console.log(JSON.stringify(error)); - toastService.error(`Failed to delete user '${username}'.`); + let message; + let statusLabel = enabled ? 'enable' : 'disable'; + if (users.length > 1) { + message = `Failed to ${statusLabel} users.` + } else { + message = + `Failed to ${statusLabel} user '${users[0].UserName}'.` + } + toastService.error(message); }) .finally(() => { + getLocalUsers(); $scope.loading = false; }); } @@ -257,7 +323,7 @@ window.angular && (function(angular) { // Some form controls will be disabled for root users: // edit enabled status, edit username, edit role const isRoot = - newUser ? false : user.UserName === 'root' ? true : false; + newUser ? false : checkIfRoot(user) ? true : false; // Array of existing usernames (excluding current user instance) const existingUsernames = $scope.localUsers.reduce((acc, val) => { @@ -328,10 +394,10 @@ window.angular && (function(angular) { } /** - * Intiate remove user modal - * @param {*} user + * Intiate remove users modal + * @param {*} users */ - function initRemoveModal(user) { + function initRemoveModal(users) { const template = require('./user-accounts-modal-remove.html'); $uibModal .open({ @@ -340,17 +406,12 @@ window.angular && (function(angular) { ariaLabelledBy: 'dialog_label', controllerAs: 'modalCtrl', controller: function() { - this.user = user.UserName; + this.users = users; } }) .result .then(() => { - const isRoot = user.UserName === 'root' ? true : false; - if (isRoot) { - toastService.error(`Cannot delete 'root' user.`) - return; - } - deleteUser(user.UserName); + deleteUsers(users); }) .catch( () => { @@ -368,13 +429,32 @@ window.angular && (function(angular) { initUserModal(value.row); break; case 'Delete': - initRemoveModal(value.row); + initRemoveModal([value.row]); break; default: } }; /** + * Callback when batch action emitted from table + */ + $scope.onEmitBatchAction = (value) => { + switch (value.action) { + case 'delete': + initRemoveModal(value.filteredRows); + break; + case 'enable': + updateUserStatus(value.filteredRows, true) + break; + case 'disable': + updateUserStatus(value.filteredRows, false) + break; + default: + break; + } + }; + + /** * Callback when 'Account settings policy' button clicked */ $scope.onClickAccountSettingsPolicy = () => { diff --git a/app/users/controllers/user-accounts-modal-remove.html b/app/users/controllers/user-accounts-modal-remove.html index e615251..4a3efce 100644 --- a/app/users/controllers/user-accounts-modal-remove.html +++ b/app/users/controllers/user-accounts-modal-remove.html @@ -8,7 +8,8 @@ </button> </div> <div class="modal-body"> - <p>Are you sure you want to remove user '{{modalCtrl.user}}'? This action cannot be undone.</p> + <p ng-if="modalCtrl.users.length > 1">Are you sure you want to remove {{modalCtrl.users.length}} users? This action cannot be undone.</p> + <p ng-if="modalCtrl.users.length === 1">Are you sure you want to remove user '{{modalCtrl.users[0].UserName}}'? This action cannot be undone.</p> </div> <div class="modal-footer"> <button class="btn btn-secondary" ng-click="$dismiss()" type="button"> |

