import { Component, OnInit } from '@angular/core'; import { catchError, debounceTime, last } from 'rxjs/operators'; import { AuthRoles } from 'src/app/models/auth/auth-roles.enum'; import { AuthUserDTO } from 'src/app/models/auth/auth-user.dto'; import { AuthService } from 'src/app/services/auth/auth.service'; import { ConfirmationDialogService } from 'src/app/services/confirmation-dialog/confirmation-dialog.service'; import { SpinnerService } from 'src/app/services/spinner/spinner.service'; import { ToastService } from 'src/app/services/toast/toast.service'; import { Table } from 'primeng/table'; import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum'; import { RegisterErrorMessages } from 'src/app/models/auth/register-error-messages.enum'; import { ErrorDTO } from 'src/app/models/error/error-dto'; import { FormBuilder, FormGroup } from '@angular/forms'; import { AuthUserSelectCriterion } from 'src/app/models/selection/auth-user/auth-user-select-criterion.dto'; import { LazyLoadEvent } from 'primeng/api'; import { throwError } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; @Component({ selector: 'app-auth-user', templateUrl: './auth-user.component.html', styleUrls: ['./auth-user.component.scss'] }) export class AuthUserComponent implements OnInit { users: AuthUserDTO[]; statuses: any[]; loading = true; activityValues: number[] = [0, 100]; clonedUsers: { [s: string]: AuthUserDTO; } = {}; isEditingNew: boolean = false; authRoles = [ { label: AuthRoles[AuthRoles.Normal].toString(), value: AuthRoles.Normal }, { label: AuthRoles[AuthRoles.Admin].toString(), value: AuthRoles.Admin } ] newUserTemplate: AuthUserDTO = { id: null, firstName: "", lastName: "", eMail: "", password: "", authRole: AuthRoles.Normal }; isFirstNameInvalid: boolean = false; isLastNameInvalid: boolean = false; isEMailInvalid: boolean = false; isPasswordInvalid: boolean = false; loggedInUserEMail: string = ""; filterForm: FormGroup; searchCriterions: AuthUserSelectCriterion; totalRecords: number; constructor( private authService: AuthService, private spinnerService: SpinnerService, private toastService: ToastService, private confirmDialog: ConfirmationDialogService, private fb: FormBuilder, private translate: TranslateService ) { } ngOnInit(): void { this.loggedInUserEMail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken()); this.searchCriterions = { firstName: null, lastName: null, eMail: null, authRole: null, pageIndex: 0, pageSize: 10, sortColumn: null, sortDirection: null }; this.setFilterForm(); this.loadNextPage(); } setFilterForm() { this.filterForm = this.fb.group({ firstName: [null], lastName: [null], eMail: [null], authRole: [null] }); this.filterForm.valueChanges.pipe( debounceTime(600) ).subscribe(changes => { if (changes.firstName) { this.searchCriterions.firstName = changes.firstName; } else { this.searchCriterions.firstName = undefined; } if (changes.lastName) { this.searchCriterions.lastName = changes.lastName; } else { this.searchCriterions.lastName = undefined; } if (changes.eMail) { this.searchCriterions.eMail = changes.eMail; } else { this.searchCriterions.eMail = undefined; } if (changes.authRole != null) { this.searchCriterions.authRole = changes.authRole; } else { this.searchCriterions.authRole = undefined; } if (this.searchCriterions.pageSize) this.searchCriterions.pageSize = 10; if (this.searchCriterions.pageSize) this.searchCriterions.pageIndex = 0; this.loadNextPage(); }); } loadNextPage() { this.authService.getFilteredUsers(this.searchCriterions).pipe(catchError(err => { this.loading = false; return throwError(err); })).subscribe(list => { this.totalRecords = list.totalCount; this.users = list.users; this.loading = false; }); } nextPage(event: LazyLoadEvent) { this.searchCriterions.pageSize = event.rows; if (event.first != null && event.rows != null) this.searchCriterions.pageIndex = event.first / event.rows; this.searchCriterions.sortColumn = event.sortField; this.searchCriterions.sortDirection = event.sortOrder === 1 ? 'asc' : event.sortOrder === -1 ? 'desc' : 'asc'; if (event.filters) { // + "" => convert to string this.searchCriterions.firstName = event.filters.firstName ? event.filters.firstName + "" : undefined; this.searchCriterions.lastName = event.filters.lastName ? event.filters.lastName + "" : undefined; this.searchCriterions.eMail = event.filters.eMail ? event.filters.eMail + "" : undefined; this.searchCriterions.authRole = event.filters.authRole ? +event.filters.authRole : undefined; } this.loadNextPage(); } resetFilters(table: Table) { this.filterForm.reset(); } initUserList(): void { this.spinnerService.showSpinner(); this.authService.getAllUsers() .pipe(catchError(err => { this.spinnerService.hideSpinner(); throw err; })) .subscribe(users => { this.users = users; this.spinnerService.hideSpinner(); }); } onRowEditInit(table: Table, user: AuthUserDTO, index: number) { this.clonedUsers[index] = { ...user }; } onRowEditSave(table: Table, newUser: AuthUserDTO, index: number) { const oldUser = this.clonedUsers[index]; delete this.clonedUsers[index]; if (JSON.stringify(oldUser) === JSON.stringify(newUser) && !this.isEditingNew) { return; } if (this.isEditingNew && JSON.stringify(newUser) === JSON.stringify(this.newUserTemplate)) { this.isEditingNew = false; this.users.splice(index, 1); return; } this.isFirstNameInvalid = newUser.firstName == ""; this.isLastNameInvalid = newUser.lastName == ""; this.isEMailInvalid = newUser.eMail == ""; this.isPasswordInvalid = newUser.password == ""; if ( this.isEditingNew && ( newUser.firstName == "" || newUser.lastName == "" || newUser.eMail == "" ) ) { table.initRowEdit(newUser); return; } if (this.isEditingNew) { this.spinnerService.showSpinner(); this.authService.register(newUser).pipe(catchError(error => { this.spinnerService.hideSpinner(); if (error.error !== null) { const err: ErrorDTO = error.error; if (err.errorCode === ServiceErrorCode.InvalidData && err.message === RegisterErrorMessages.InvalidEMail) { this.isEMailInvalid = true; this.toastService.error(this.translate.instant('admin.auth_users.message.invalid_email'), this.translate.instant('admin.auth_users.message.invalid_email_d', { eMail: newUser.eMail })); } else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === RegisterErrorMessages.UserAlreadyExists) { this.isEMailInvalid = true; this.toastService.error(this.translate.instant('admin.auth_users.message.user_already_exists'), this.translate.instant('admin.auth_users.message.user_already_exists_d', { eMail: newUser.eMail })); } error.error = null; table.initRowEdit(newUser); } this.spinnerService.hideSpinner(); throw error; })) .subscribe(_ => { this.initUserList(); this.spinnerService.hideSpinner(); this.toastService.success(this.translate.instant('admin.auth_users.message.user_added'), this.translate.instant('admin.auth_users.message.user_added_d', { eMail: newUser.eMail })); this.isEditingNew = false; }); this.triggerUserChangeDetection(); return; } this.spinnerService.showSpinner(); this.authService.updateUserAsAdmin({ authUserDTO: oldUser, newAuthUserDTO: newUser, changePassword: newUser.password != "" }).pipe(catchError(err => { this.spinnerService.hideSpinner(); this.toastService.error(this.translate.instant('admin.auth_users.message.user_change_failed'), this.translate.instant('admin.auth_users.message.user_change_failed_d', { eMail: newUser.eMail })); this.initUserList(); throw err; })) .subscribe(_ => { this.initUserList(); this.spinnerService.hideSpinner(); this.toastService.success(this.translate.instant('admin.auth_users.message.user_changed'), this.translate.instant('admin.auth_users.message.user_changed_d', { eMail: newUser.eMail })); }); this.triggerUserChangeDetection(); } onRowEditCancel(user: AuthUserDTO, index: number) { this.isFirstNameInvalid = false; this.isLastNameInvalid = false; this.isEMailInvalid = false; this.isPasswordInvalid = false; if (this.isEditingNew) { this.users.splice(index, 1); this.triggerUserChangeDetection(); delete this.clonedUsers[index]; this.isEditingNew = false; return; } this.users[index] = this.clonedUsers[index]; this.triggerUserChangeDetection(); delete this.clonedUsers[index]; } deleteUser(user: AuthUserDTO) { if (user.eMail == this.loggedInUserEMail) { this.toastService.error(this.translate.instant('admin.auth_users.message.cannot_delete_user'), this.translate.instant('admin.auth_users.message.logon_with_another_user')); return; } this.confirmDialog.confirmDialog( this.translate.instant('admin.auth_users.message.user_delete'), this.translate.instant('admin.auth_users.message.user_delete_q', { eMail: user.eMail }), () => { this.spinnerService.showSpinner(); this.authService.deleteUserByMail(user.eMail) .pipe(catchError(err => { this.spinnerService.hideSpinner(); throw err; })) .subscribe(_ => { this.initUserList(); this.spinnerService.hideSpinner(); this.toastService.success(this.translate.instant('admin.auth_users.message.user_deleted'), this.translate.instant('admin.auth_users.message.user_deleted_d', { eMail: user.eMail })); }); }); } addUser(table: Table) { const newUser = JSON.parse(JSON.stringify(this.newUserTemplate)); newUser.id = Math.max.apply(Math, this.users.map(function (u) { return u.id; })) + 1; console.log(newUser); this.users.push(newUser); this.triggerUserChangeDetection(); table.initRowEdit(newUser); const index = this.users.findIndex(u => u.eMail == newUser.eMail); this.onRowEditInit(table, newUser, index); this.isEditingNew = true; } triggerUserChangeDetection() { // trigger change detection (https://github.com/primefaces/primeng/issues/2219) this.users = this.users.slice(); } }