From 5c2b9ed3db2cc23a988178bd83822eaac37287b3 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 25 Jul 2026 18:23:51 +0200 Subject: [PATCH] Improve user experience of users table in admin control panel --- .../admin-users/admin-users.component.ts | 17 ++++++----- .../src/app/pages/admin/admin-page.routes.ts | 30 ++++++++++++++----- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/apps/client/src/app/components/admin-users/admin-users.component.ts b/apps/client/src/app/components/admin-users/admin-users.component.ts index 305c48dcf9..5f4d8811cc 100644 --- a/apps/client/src/app/components/admin-users/admin-users.component.ts +++ b/apps/client/src/app/components/admin-users/admin-users.component.ts @@ -236,12 +236,17 @@ export class GfAdminUsersComponent implements OnInit { .deleteUser(aId) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { - this.router.navigate(['..'], { relativeTo: this.route }); + this.router.navigate(this.routerLinkAdminControlUsers); + + this.fetchUsers({ + pageIndex: this.paginator().pageIndex, + showLoading: false + }); }); }, confirmType: ConfirmationDialogType.Warn, discardFn: () => { - this.router.navigate(['..'], { relativeTo: this.route }); + this.router.navigate(this.routerLinkAdminControlUsers); }, title: $localize`Do you really want to delete this user?` }); @@ -283,9 +288,7 @@ export class GfAdminUsersComponent implements OnInit { } protected onOpenUserDetailDialog(userId: string) { - this.router.navigate( - internalRoutes.adminControl.subRoutes.users.routerLink.concat(userId) - ); + this.router.navigate(this.routerLinkAdminControlUsers.concat(userId)); } private fetchUsers({ @@ -341,9 +344,7 @@ export class GfAdminUsersComponent implements OnInit { if (data?.action === 'delete' && data?.userId) { this.onDeleteUser(data.userId); } else { - this.router.navigate( - internalRoutes.adminControl.subRoutes.users.routerLink - ); + this.router.navigate(this.routerLinkAdminControlUsers); } }); } diff --git a/apps/client/src/app/pages/admin/admin-page.routes.ts b/apps/client/src/app/pages/admin/admin-page.routes.ts index c5309edbbe..30d6728ae9 100644 --- a/apps/client/src/app/pages/admin/admin-page.routes.ts +++ b/apps/client/src/app/pages/admin/admin-page.routes.ts @@ -6,10 +6,31 @@ import { GfAdminUsersComponent } from '@ghostfolio/client/components/admin-users import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { Routes } from '@angular/router'; +import { Routes, UrlMatcher, UrlSegment } from '@angular/router'; import { AdminPageComponent } from './admin-page.component'; +// Matches both the users list and the user detail dialog route within a single +// route configuration so that the component is reused (and not re-created) when +// the user detail dialog is opened or closed +const usersMatcher: UrlMatcher = (segments: UrlSegment[]) => { + if ( + segments[0]?.path !== internalRoutes.adminControl.subRoutes.users.path || + segments.length > 2 + ) { + return null; + } + + if (segments.length === 2) { + return { + consumed: segments, + posParams: { userId: segments[1] } + }; + } + + return { consumed: segments }; +}; + export const routes: Routes = [ { canActivate: [AuthGuard], @@ -35,13 +56,8 @@ export const routes: Routes = [ title: internalRoutes.adminControl.subRoutes.settings.title }, { - path: internalRoutes.adminControl.subRoutes.users.path, - component: GfAdminUsersComponent, - title: internalRoutes.adminControl.subRoutes.users.title - }, - { - path: `${internalRoutes.adminControl.subRoutes.users.path}/:userId`, component: GfAdminUsersComponent, + matcher: usersMatcher, title: internalRoutes.adminControl.subRoutes.users.title } ],