import { Component, OnInit } from '@angular/core'; import { SpinnerService } from '@core/services/spinner.service'; import { AddEditUser, PaginatedUsersResponse, UserFromApi } from '@core/typings/client-user.typing'; import { UserStatus } from '@core/typings/user.typing'; import { ImportUsersModalComponent } from '@features/platform-admin/internal-admins/import-users-modal/import-users-modal.component'; import { ALL_SKIP_FILTER, BulkAction, DebounceFactory, PaginationOptions, SelectOption, TableDataDownloadFormat, TableDataFactory, TopLevelFilter, TopLevelFilterOptionsConfig } from '@yourcause/common'; import { CachedAttr, CACHE_TYPES } from '@yourcause/common/cache'; import { I18nService } from '@yourcause/common/i18n'; import { ConfirmationModalComponent, ModalFactory } from '@yourcause/common/modals'; import { AddEditUserModalComponent } from '../add-edit-user-modal/add-edit-user-modal.component'; import { UserExportService } from '../user-export.service'; import { UserService } from '../user.service'; @Component({ selector: 'gc-users-page', templateUrl: 'users-page.component.html', styleUrls: [ './users-page.component.scss' ] }) export class UsersPageComponent implements OnInit { tableDataFactory: TableDataFactory; stats: SelectOption[] = []; bulkActions: BulkAction[]; bulkSelected: UserFromApi[]; showBulkActions = true; TableDataDownloadFormat = TableDataDownloadFormat; statusOptions: TopLevelFilterOptionsConfig = { selectOptions: [{ value: ALL_SKIP_FILTER, display: this.i18n.translate( 'PROGRAM:textAllUsers', {}, 'All users' ) }, { value: 'active', customValue: false, customColumn: 'isDeactivated', display: this.i18n.translate( 'GLOBAL:textActiveUsers', {}, 'Active users' ) }, { value: 'inactive', customValue: true, customColumn: 'isDeactivated', display: this.i18n.translate( 'GLOBAL:textInactiveUsers', {}, 'Inactive users' ) }] }; topLevelFilters: TopLevelFilter[] = []; currentUserId = this.userService.user.id; @CachedAttr( CACHE_TYPES.LOCALSTORAGE, false ) isInactive: boolean; userStatus: UserStatus = UserStatus.Active; constructor ( private i18n: I18nService, private modalFactory: ModalFactory, private userService: UserService, private spinnerService: SpinnerService, private userExportService: UserExportService ) { } ngOnInit () { this.setTopLevelFilters(); this.setBulkActions(); this.tableDataFactory = DebounceFactory.createSimple( async (options: PaginationOptions) => { const result = await this.userService.getUsersPaginated(options); this.setStats(result); return { success: true, data: { recordCount: result.users.recordCount, records: result.users.records } }; } ); } setTopLevelFilters () { this.topLevelFilters = [ new TopLevelFilter( 'text', 'fullNameOrEmail', '', this.i18n.translate( 'common:textSearchByUserNameOrEmail', {}, 'Search by user name or email' ), undefined, undefined, [{ column: 'fullName', filterType: 'cn' }, { column: 'email', filterType: 'cn' }] ), new TopLevelFilter( 'typeaheadSingleEquals', 'userStatus', 'active', '', this.statusOptions, this.i18n.translate( 'GLOBAL:textUserStatus', {}, 'User status' ) ) ]; } setBulkActions () { if (this.isInactive) { this.bulkActions = []; } else { this.bulkActions = [{ label: this.i18n.translate('GLOBAL:btnDeactivate'), exec: (users: UserFromApi[]) => { const userIds = users.map((user) => user.id); this.deactivateUsers(userIds); }, disabled: (users: UserFromApi[]) => { return users.every(val => { return val.isDeactivated || val.id === this.currentUserId; }); } }]; } } onTopLevelFilterChange (filter: TopLevelFilter) { if (filter.column === 'userStatus') { this.isInactive = filter.value === 'inactive'; this.setBulkActions(); if (filter.value === 'inactive') { this.userStatus = UserStatus.Inactive; } else if (filter.value === 'active') { this.userStatus = UserStatus.Active; } else { this.userStatus = UserStatus.All; } } } bulkSelectedChanged (bulkSelected: UserFromApi[]) { this.bulkSelected = bulkSelected; } setStats (result: PaginatedUsersResponse) { this.stats = Object.keys(result).filter((stat) => { return stat !== 'users'; }).map((stat) => { let display: string; switch (stat) { case 'activeUsers': display = this.i18n.translate( 'GLOBAL:textActiveUsers', {}, 'Active users' ); break; case 'inActiveUsers': display = this.i18n.translate( 'GLOBAL:textInactiveUsers', {}, 'Inactive users' ); break; case 'usersAddedToAccount': display = this.i18n.translate( 'GLOBAL:textTotalUsers', {}, 'Total users' ); break; case 'usersWaitingForRegistration': display = this.i18n.translate( 'GLOBAL:WAITING_FOR_REGISTRATION', {}, 'Not registered' ); break; default: display = ''; break; } return { display, value: +(result as any)[stat] }; }); } async createUser () { const response = await this.modalFactory.open( AddEditUserModalComponent, {} ); if (response) { this.spinnerService.startSpinner(); const success = await this.userService.addEditUser(response); if (success) { await this.resetTable(); } this.spinnerService.stopSpinner(); } } async activateUserToggle (row: UserFromApi, type: 'Activate' | 'Deactivate') { const isActivate = type === 'Activate'; const deps = { modalHeader: this.i18n.translate( isActivate ? 'GLOBAL:hdrActivateUser' : 'GLOBAL:hdrDeactivateUser', {}, isActivate ? 'Activate User' : 'Deactivate User' ), confirmButtonText: this.i18n.translate( isActivate ? 'GLOBAL:textActivate' : 'GLOBAL:btnDeactivate', {}, isActivate ? 'Activate' : 'Deactivate' ), confirmText: this.i18n.translate( isActivate ? 'USERS:textAreYouSureActivateUser' : 'USERS:textAreYouSureDeactivateUser', { name: row.fullName }, isActivate ? 'Are you sure you want to activate __name__?' : 'Are you sure you want to deactivate __name__?' ) }; const proceed = await this.modalFactory.open( ConfirmationModalComponent, deps ); if (proceed) { this.spinnerService.startSpinner(); if (type === 'Deactivate') { await this.userService.deactivateUser([row.id]); } else { await this.userService.activateUser(row.id); } await this.resetTable(); this.spinnerService.stopSpinner(); } } async resetTable () { this.tableDataFactory.reset.emit(); this.bulkSelected = []; await this.userService.resetAllUsers(); } async onImportClick () { const result = await this.modalFactory.open( ImportUsersModalComponent, {} ); if (result) { this.spinnerService.startSpinner(); await this.userService.handleUsersImport(result); await this.resetTable(); this.spinnerService.stopSpinner(); } } async exportRoles (format: TableDataDownloadFormat) { this.spinnerService.startSpinner(); await this.userExportService.exportRoles(format); this.spinnerService.stopSpinner(); } async exportWFLs (format: TableDataDownloadFormat) { this.spinnerService.startSpinner(); await this.userExportService.exportWFLs(format); this.spinnerService.stopSpinner(); } async exportUserWFLs (format: TableDataDownloadFormat) { this.spinnerService.startSpinner(); await this.userExportService.exportUserWFLs(format); this.spinnerService.stopSpinner(); } async exportUserRoles (format: TableDataDownloadFormat) { this.spinnerService.startSpinner(); await this.userExportService.exportUserRoles(format); this.spinnerService.stopSpinner(); } async exportUsersGMPortal (format: TableDataDownloadFormat) { this.spinnerService.startSpinner(); if (this.userStatus === UserStatus.All){ await this.userExportService.exportUsersGMPortal(true, true, format); } else if (this.userStatus === UserStatus.Active) { await this.userExportService.exportUsersGMPortal(true, false, format); } else { await this.userExportService.exportUsersGMPortal(false, true, format); } this.spinnerService.stopSpinner(); } async deactivateUsers (userIds: number[]) { const deps = { modalHeader: this.i18n.translate( 'GLOBAL:hdrDeactivateUsers', {}, 'Deactivate Users' ), confirmButtonText: this.i18n.translate( 'GLOBAL:btnDeactivate', {}, 'Deactivate' ), confirmText: `
${this.i18n.translate( 'GLOBAL:textTotalUsers', {}, 'Total Users' )}
${ this.bulkSelected.length }
${this.i18n.translate( 'USERS:textBulkDeactivatedUserDescription', {}, 'Deactivated users cannot access the system, be added to workflow levels, ' + 'roles, audiences, or be sent reports and added to a report schedule. ' + ' Are you sure you want to deactivate the selected users?' )}
` }; const proceed = await this.modalFactory.open( ConfirmationModalComponent, deps ); if (proceed) { this.spinnerService.startSpinner(); await this.userService.deactivateUser(userIds); await this.resetTable(); this.spinnerService.stopSpinner(); } } async updateGrantManager (existingUser: AddEditUser) { const response = await this.modalFactory.open( AddEditUserModalComponent, { existingUser } ); if (response) { this.spinnerService.startSpinner(); const success = await this.userService.addEditUser({ ...response, id: existingUser.id }); if (success) { await this.resetTable(); } this.spinnerService.stopSpinner(); } } }