fix: stabilize admin user UI state
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { Component, DestroyRef, inject, signal } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
@@ -7,7 +8,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { filter, finalize, of, switchMap, take } from 'rxjs';
|
||||
import { EMPTY, Subject, catchError, filter, finalize, of, startWith, switchMap, take, tap } from 'rxjs';
|
||||
import { AuthStore } from '../../core/auth/auth-store';
|
||||
import { AdminUsersApi } from '../../core/users/admin-users-api';
|
||||
import { UsersApi } from '../../core/users/users-api';
|
||||
@@ -41,6 +42,8 @@ export class Users {
|
||||
private readonly adminUsersApi = inject(AdminUsersApi);
|
||||
private readonly authStore = inject(AuthStore);
|
||||
private readonly dialog = inject(MatDialog);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly directoryRequests = new Subject<boolean>();
|
||||
|
||||
protected readonly isAdmin = this.authStore.isGlobalAdmin;
|
||||
protected readonly currentUser = this.authStore.currentUser;
|
||||
@@ -54,30 +57,42 @@ export class Users {
|
||||
protected readonly limit = 20;
|
||||
protected readonly editingUserId = signal<number | null>(null);
|
||||
protected readonly assignmentUserId = signal<number | null>(null);
|
||||
protected readonly assignmentBusyUserId = signal<number | null>(null);
|
||||
protected readonly pendingUserId = signal<number | null>(null);
|
||||
|
||||
constructor() {
|
||||
this.loadDirectory();
|
||||
this.directoryRequests
|
||||
.pipe(
|
||||
startWith(true),
|
||||
switchMap((showLoading) => {
|
||||
if (showLoading) this.loading.set(true);
|
||||
this.loadError.set(null);
|
||||
const search = this.search();
|
||||
return this.usersApi
|
||||
.loadDirectory({ page: this.page(), limit: this.limit, ...(search ? { search } : {}) })
|
||||
.pipe(
|
||||
tap((directory) => this.directory.set(directory)),
|
||||
catchError((error: HttpErrorResponse) => {
|
||||
this.directory.set(null);
|
||||
this.loadError.set(this.errorMessage(error, 'Benutzer konnten nicht geladen werden.'));
|
||||
return EMPTY;
|
||||
}),
|
||||
finalize(() => this.loading.set(false)),
|
||||
);
|
||||
}),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
protected loadDirectory(): void {
|
||||
this.loading.set(true);
|
||||
this.loadError.set(null);
|
||||
const search = this.search();
|
||||
this.usersApi
|
||||
.loadDirectory({ page: this.page(), limit: this.limit, ...(search ? { search } : {}) })
|
||||
.pipe(finalize(() => this.loading.set(false)))
|
||||
.subscribe({
|
||||
next: (directory) => this.directory.set(directory),
|
||||
error: (error: HttpErrorResponse) => {
|
||||
this.directory.set(null);
|
||||
this.loadError.set(this.errorMessage(error, 'Benutzer konnten nicht geladen werden.'));
|
||||
},
|
||||
});
|
||||
protected loadDirectory(showLoading = true): void {
|
||||
this.directoryRequests.next(showLoading);
|
||||
}
|
||||
|
||||
protected submitSearch(): void {
|
||||
this.search.set(this.searchDraft().trim());
|
||||
const search = this.searchDraft().trim();
|
||||
if (this.loading() && search === this.search() && this.page() === 1) return;
|
||||
this.search.set(search);
|
||||
this.page.set(1);
|
||||
this.loadDirectory();
|
||||
}
|
||||
@@ -129,12 +144,14 @@ export class Users {
|
||||
}
|
||||
|
||||
protected toggleEdit(userId: number): void {
|
||||
if (this.assignmentBusyUserId() !== null) return;
|
||||
this.assignmentUserId.set(null);
|
||||
this.editingUserId.update((value) => (value === userId ? null : userId));
|
||||
this.mutationError.set(null);
|
||||
}
|
||||
|
||||
protected toggleAssignments(userId: number): void {
|
||||
if (this.assignmentBusyUserId() !== null) return;
|
||||
this.editingUserId.set(null);
|
||||
this.assignmentUserId.update((value) => (value === userId ? null : userId));
|
||||
this.mutationError.set(null);
|
||||
@@ -149,12 +166,15 @@ export class Users {
|
||||
lastName: value.lastName,
|
||||
});
|
||||
const roleId = user.role?.id;
|
||||
let profileSaved = false;
|
||||
profileRequest
|
||||
.pipe(
|
||||
tap(() => (profileSaved = true)),
|
||||
switchMap(() =>
|
||||
roleId === value.role ? of(user) : this.adminUsersApi.updateRole(user.id, { role: value.role }),
|
||||
),
|
||||
finalize(() => this.pendingUserId.set(null)),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
@@ -163,7 +183,7 @@ export class Users {
|
||||
},
|
||||
error: (error: HttpErrorResponse) => {
|
||||
this.mutationError.set(this.errorMessage(error, 'Änderung fehlgeschlagen.'));
|
||||
this.loadDirectory();
|
||||
if (profileSaved) this.loadDirectory();
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -182,7 +202,7 @@ export class Users {
|
||||
restoreFocus: true,
|
||||
})
|
||||
.afterClosed()
|
||||
.pipe(filter(Boolean), take(1))
|
||||
.pipe(filter(Boolean), take(1), takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe(() => this.updateStatus(user.id, status));
|
||||
}
|
||||
|
||||
@@ -191,7 +211,11 @@ export class Users {
|
||||
}
|
||||
|
||||
protected assignmentsChanged(): void {
|
||||
this.loadDirectory();
|
||||
this.loadDirectory(false);
|
||||
}
|
||||
|
||||
protected assignmentBusyChanged(userId: number, busy: boolean): void {
|
||||
this.assignmentBusyUserId.set(busy ? userId : null);
|
||||
}
|
||||
|
||||
private updateStatus(userId: number, status: AdminUserStatusId): void {
|
||||
@@ -199,7 +223,7 @@ export class Users {
|
||||
this.mutationError.set(null);
|
||||
this.adminUsersApi
|
||||
.updateStatus(userId, { status })
|
||||
.pipe(finalize(() => this.pendingUserId.set(null)))
|
||||
.pipe(finalize(() => this.pendingUserId.set(null)), takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe({
|
||||
next: () => this.loadDirectory(),
|
||||
error: (error: HttpErrorResponse) =>
|
||||
|
||||
Reference in New Issue
Block a user