1<template> 2 <b-container fluid="xl"> 3 <page-title /> 4 <b-row> 5 <b-col xl="9" class="text-right"> 6 <b-button variant="link" @click="initModalSettings"> 7 <icon-settings /> 8 {{ $t('pageUserManagement.accountPolicySettings') }} 9 </b-button> 10 <b-button 11 variant="primary" 12 data-test-id="userManagement-button-addUser" 13 @click="initModalUser(null)" 14 > 15 <icon-add /> 16 {{ $t('pageUserManagement.addUser') }} 17 </b-button> 18 </b-col> 19 </b-row> 20 <b-row> 21 <b-col xl="9"> 22 <table-toolbar 23 ref="toolbar" 24 :selected-items-count="selectedRows.length" 25 :actions="tableToolbarActions" 26 @clear-selected="clearSelectedRows($refs.table)" 27 @batch-action="onBatchAction" 28 /> 29 <b-table 30 ref="table" 31 responsive="md" 32 selectable 33 show-empty 34 no-select-on-click 35 hover 36 :busy="isBusy" 37 :fields="fields" 38 :items="tableItems" 39 :empty-text="$t('global.table.emptyMessage')" 40 @row-selected="onRowSelected($event, tableItems.length)" 41 > 42 <!-- Checkbox column --> 43 <template #head(checkbox)> 44 <b-form-checkbox 45 v-model="tableHeaderCheckboxModel" 46 data-test-id="userManagement-checkbox-tableHeaderCheckbox" 47 :indeterminate="tableHeaderCheckboxIndeterminate" 48 @change="onChangeHeaderCheckbox($refs.table)" 49 > 50 <span class="sr-only">{{ $t('global.table.selectAll') }}</span> 51 </b-form-checkbox> 52 </template> 53 <template #cell(checkbox)="row"> 54 <b-form-checkbox 55 v-model="row.rowSelected" 56 data-test-id="userManagement-checkbox-toggleSelectRow" 57 @change="toggleSelectRow($refs.table, row.index)" 58 > 59 <span class="sr-only">{{ $t('global.table.selectItem') }}</span> 60 </b-form-checkbox> 61 </template> 62 63 <!-- table actions column --> 64 <template #cell(actions)="{ item }"> 65 <table-row-action 66 v-for="(action, index) in item.actions" 67 :key="index" 68 :value="action.value" 69 :enabled="action.enabled" 70 :title="action.title" 71 @click-table-action="onTableRowAction($event, item)" 72 > 73 <template #icon> 74 <icon-edit 75 v-if="action.value === 'edit'" 76 :data-test-id="`userManagement-tableRowAction-edit-${index}`" 77 /> 78 <icon-trashcan 79 v-if="action.value === 'delete'" 80 :data-test-id="`userManagement-tableRowAction-delete-${index}`" 81 /> 82 </template> 83 </table-row-action> 84 </template> 85 </b-table> 86 </b-col> 87 </b-row> 88 <b-row> 89 <b-col xl="8"> 90 <b-button 91 v-b-toggle.collapse-role-table 92 data-test-id="userManagement-button-viewPrivilegeRoleDescriptions" 93 variant="link" 94 class="mt-3" 95 > 96 <icon-chevron /> 97 {{ $t('pageUserManagement.viewPrivilegeRoleDescriptions') }} 98 </b-button> 99 <b-collapse id="collapse-role-table" class="mt-3"> 100 <table-roles /> 101 </b-collapse> 102 </b-col> 103 </b-row> 104 <!-- Modals --> 105 <modal-settings :settings="settings" @ok="saveAccountSettings" /> 106 <modal-user 107 :user="activeUser" 108 :password-requirements="passwordRequirements" 109 @ok="saveUser" 110 @hidden="activeUser = null" 111 /> 112 </b-container> 113</template> 114 115<script> 116import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; 117import IconEdit from '@carbon/icons-vue/es/edit/20'; 118import IconAdd from '@carbon/icons-vue/es/add--alt/20'; 119import IconSettings from '@carbon/icons-vue/es/settings/20'; 120import IconChevron from '@carbon/icons-vue/es/chevron--up/20'; 121 122import ModalUser from './ModalUser'; 123import ModalSettings from './ModalSettings'; 124import PageTitle from '@/components/Global/PageTitle'; 125import TableRoles from './TableRoles'; 126import TableToolbar from '@/components/Global/TableToolbar'; 127import TableRowAction from '@/components/Global/TableRowAction'; 128 129import BVTableSelectableMixin, { 130 selectedRows, 131 tableHeaderCheckboxModel, 132 tableHeaderCheckboxIndeterminate, 133} from '@/components/Mixins/BVTableSelectableMixin'; 134import BVToastMixin from '@/components/Mixins/BVToastMixin'; 135import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; 136 137export default { 138 name: 'UserManagement', 139 components: { 140 IconAdd, 141 IconChevron, 142 IconEdit, 143 IconSettings, 144 IconTrashcan, 145 ModalSettings, 146 ModalUser, 147 PageTitle, 148 TableRoles, 149 TableRowAction, 150 TableToolbar, 151 }, 152 mixins: [BVTableSelectableMixin, BVToastMixin, LoadingBarMixin], 153 beforeRouteLeave(to, from, next) { 154 this.hideLoader(); 155 next(); 156 }, 157 data() { 158 return { 159 isBusy: true, 160 activeUser: null, 161 fields: [ 162 { 163 key: 'checkbox', 164 }, 165 { 166 key: 'username', 167 label: this.$t('pageUserManagement.table.username'), 168 }, 169 { 170 key: 'privilege', 171 label: this.$t('pageUserManagement.table.privilege'), 172 }, 173 { 174 key: 'status', 175 label: this.$t('pageUserManagement.table.status'), 176 }, 177 { 178 key: 'actions', 179 label: '', 180 tdClass: 'text-right text-nowrap', 181 }, 182 ], 183 tableToolbarActions: [ 184 { 185 value: 'delete', 186 label: this.$t('global.action.delete'), 187 }, 188 { 189 value: 'enable', 190 label: this.$t('global.action.enable'), 191 }, 192 { 193 value: 'disable', 194 label: this.$t('global.action.disable'), 195 }, 196 ], 197 selectedRows: selectedRows, 198 tableHeaderCheckboxModel: tableHeaderCheckboxModel, 199 tableHeaderCheckboxIndeterminate: tableHeaderCheckboxIndeterminate, 200 }; 201 }, 202 computed: { 203 allUsers() { 204 return this.$store.getters['userManagement/allUsers']; 205 }, 206 tableItems() { 207 // transform user data to table data 208 return this.allUsers.map((user) => { 209 return { 210 username: user.UserName, 211 privilege: user.RoleId, 212 status: user.Locked 213 ? 'Locked' 214 : user.Enabled 215 ? 'Enabled' 216 : 'Disabled', 217 actions: [ 218 { 219 value: 'edit', 220 enabled: true, 221 title: this.$t('pageUserManagement.editUser'), 222 }, 223 { 224 value: 'delete', 225 enabled: user.UserName === 'root' ? false : true, 226 title: this.$tc('pageUserManagement.deleteUser'), 227 }, 228 ], 229 ...user, 230 }; 231 }); 232 }, 233 settings() { 234 return this.$store.getters['userManagement/accountSettings']; 235 }, 236 passwordRequirements() { 237 return this.$store.getters['userManagement/accountPasswordRequirements']; 238 }, 239 }, 240 created() { 241 this.startLoader(); 242 this.$store.dispatch('userManagement/getUsers').finally(() => { 243 this.endLoader(); 244 this.isBusy = false; 245 }); 246 this.$store.dispatch('userManagement/getAccountSettings'); 247 this.$store.dispatch('userManagement/getAccountRoles'); 248 }, 249 methods: { 250 initModalUser(user) { 251 this.activeUser = user; 252 this.$bvModal.show('modal-user'); 253 }, 254 initModalDelete(user) { 255 this.$bvModal 256 .msgBoxConfirm( 257 this.$t('pageUserManagement.modal.deleteConfirmMessage', { 258 user: user.username, 259 }), 260 { 261 title: this.$tc('pageUserManagement.deleteUser'), 262 okTitle: this.$tc('pageUserManagement.deleteUser'), 263 cancelTitle: this.$t('global.action.cancel'), 264 } 265 ) 266 .then((deleteConfirmed) => { 267 if (deleteConfirmed) { 268 this.deleteUser(user); 269 } 270 }); 271 }, 272 initModalSettings() { 273 this.$bvModal.show('modal-settings'); 274 }, 275 saveUser({ isNewUser, userData }) { 276 this.startLoader(); 277 if (isNewUser) { 278 this.$store 279 .dispatch('userManagement/createUser', userData) 280 .then((success) => this.successToast(success)) 281 .catch(({ message }) => this.errorToast(message)) 282 .finally(() => this.endLoader()); 283 } else { 284 this.$store 285 .dispatch('userManagement/updateUser', userData) 286 .then((success) => this.successToast(success)) 287 .catch(({ message }) => this.errorToast(message)) 288 .finally(() => this.endLoader()); 289 } 290 }, 291 deleteUser({ username }) { 292 this.startLoader(); 293 this.$store 294 .dispatch('userManagement/deleteUser', username) 295 .then((success) => this.successToast(success)) 296 .catch(({ message }) => this.errorToast(message)) 297 .finally(() => this.endLoader()); 298 }, 299 onBatchAction(action) { 300 switch (action) { 301 case 'delete': 302 this.$bvModal 303 .msgBoxConfirm( 304 this.$tc( 305 'pageUserManagement.modal.batchDeleteConfirmMessage', 306 this.selectedRows.length 307 ), 308 { 309 title: this.$tc( 310 'pageUserManagement.deleteUser', 311 this.selectedRows.length 312 ), 313 okTitle: this.$tc( 314 'pageUserManagement.deleteUser', 315 this.selectedRows.length 316 ), 317 cancelTitle: this.$t('global.action.cancel'), 318 } 319 ) 320 .then((deleteConfirmed) => { 321 if (deleteConfirmed) { 322 this.startLoader(); 323 this.$store 324 .dispatch('userManagement/deleteUsers', this.selectedRows) 325 .then((messages) => { 326 messages.forEach(({ type, message }) => { 327 if (type === 'success') this.successToast(message); 328 if (type === 'error') this.errorToast(message); 329 }); 330 }) 331 .finally(() => this.endLoader()); 332 } 333 }); 334 break; 335 case 'enable': 336 this.startLoader(); 337 this.$store 338 .dispatch('userManagement/enableUsers', this.selectedRows) 339 .then((messages) => { 340 messages.forEach(({ type, message }) => { 341 if (type === 'success') this.successToast(message); 342 if (type === 'error') this.errorToast(message); 343 }); 344 }) 345 .finally(() => this.endLoader()); 346 break; 347 case 'disable': 348 this.startLoader(); 349 this.$store 350 .dispatch('userManagement/disableUsers', this.selectedRows) 351 .then((messages) => { 352 messages.forEach(({ type, message }) => { 353 if (type === 'success') this.successToast(message); 354 if (type === 'error') this.errorToast(message); 355 }); 356 }) 357 .finally(() => this.endLoader()); 358 break; 359 } 360 }, 361 onTableRowAction(action, row) { 362 switch (action) { 363 case 'edit': 364 this.initModalUser(row); 365 break; 366 case 'delete': 367 this.initModalDelete(row); 368 break; 369 default: 370 break; 371 } 372 }, 373 saveAccountSettings(settings) { 374 this.startLoader(); 375 this.$store 376 .dispatch('userManagement/saveAccountSettings', settings) 377 .then((message) => this.successToast(message)) 378 .catch(({ message }) => this.errorToast(message)) 379 .finally(() => this.endLoader()); 380 }, 381 }, 382}; 383</script> 384 385<style lang="scss" scoped> 386.btn.collapsed { 387 svg { 388 transform: rotate(180deg); 389 } 390} 391</style> 392