Browse Source

refactor and improve UI component

pull/5819/head
HydrallHarsh 1 week ago
parent
commit
f6b385cfa1
  1. 5
      CHANGELOG.md
  2. 34
      apps/client/src/app/components/admin-users/admin-users.component.ts
  3. 3
      apps/client/src/app/components/user-detail-dialog/interfaces/interfaces.ts
  4. 30
      apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts
  5. 18
      apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html

5
CHANGELOG.md

@ -5,12 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
- User detail dialog component to view user information in admin users management
## 2.210.0 - 2025-10-22
### Added
- Added support for data gathering by date range in the asset profile details dialog of the admin control panel
- Added user detail dialog component to view user information in admin users management
### Changed

34
apps/client/src/app/components/admin-users/admin-users.component.ts

@ -77,8 +77,8 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
public dataSource = new MatTableDataSource<AdminUsers['users'][0]>();
public defaultDateFormat: string;
public displayedColumns: string[] = [];
public deviceType: string;
public displayedColumns: string[] = [];
public getEmojiFlag = getEmojiFlag;
public hasPermissionForSubscription: boolean;
public hasPermissionToImpersonateAllUsers: boolean;
@ -103,6 +103,7 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
private tokenStorageService: TokenStorageService,
private userService: UserService
) {
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
this.info = this.dataService.fetchInfo();
this.hasPermissionForSubscription = hasPermission(
@ -132,6 +133,14 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
];
}
this.route.queryParams
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((params) => {
if (params['userDetailDialog'] && params['userId']) {
this.openUserDetailDialog(params['userId']);
}
});
this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((state) => {
@ -156,20 +165,12 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
personOutline,
trashOutline
});
this.deviceType = this.deviceService.getDeviceInfo().deviceType;
this.route.queryParams
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((params) => {
if (params['userDetailDialog'] && params['userId']) {
this.openUserDetailDialog(params['userId']);
}
});
}
public ngOnInit() {
this.fetchUsers();
}
public onOpenUserDetailDialog(userId: string) {
this.router.navigate([], {
queryParams: { userId, userDetailDialog: true }
@ -178,14 +179,16 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
private openUserDetailDialog(userId: string) {
// Find the user data from the current dataSource
const userData = this.dataSource.data.find((user) => user.id === userId);
const userData = this.dataSource.data.find(({ id }) => {
return id === userId;
});
const dialogRef = this.dialog.open(GfUserDetailDialogComponent, {
autoFocus: false,
data: {
userData,
userId,
deviceType: this.deviceType,
userData: userData // Pass the user data
deviceType: this.deviceType
} as UserDetailDialogParams,
height: this.deviceType === 'mobile' ? '80vh' : '60vh',
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
@ -195,10 +198,11 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit {
.afterClosed()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
this.fetchUsers(); // Refresh the users list
this.router.navigate(['.'], { relativeTo: this.route }); // Clear query params
this.fetchUsers();
this.router.navigate(['.'], { relativeTo: this.route });
});
}
public formatDistanceToNow(aDateString: string) {
if (aDateString) {
const distanceString = formatDistanceToNowStrict(parseISO(aDateString), {

3
apps/client/src/app/components/user-detail-dialog/interfaces/interfaces.ts

@ -2,6 +2,5 @@ import { AdminUsers } from '@ghostfolio/common/interfaces';
export interface UserDetailDialogParams {
deviceType: string;
userData?: AdminUsers['users'][0];
userId: string;
userData: AdminUsers['users'][0];
}

30
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts

@ -6,18 +6,16 @@ import { GfValueComponent } from '@ghostfolio/ui/value';
import { CommonModule } from '@angular/common';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
CUSTOM_ELEMENTS_SCHEMA,
Inject,
OnDestroy,
OnInit,
ChangeDetectorRef
OnInit
} from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MatDialogModule } from '@angular/material/dialog';
import { addIcons } from 'ionicons';
import { personOutline } from 'ionicons/icons';
import { Subject } from 'rxjs';
import { UserDetailDialogParams } from './interfaces/interfaces';
@ -39,20 +37,15 @@ import { UserDetailDialogParams } from './interfaces/interfaces';
templateUrl: './user-detail-dialog.html'
})
export class GfUserDetailDialogComponent implements OnDestroy, OnInit {
public isLoading = false;
public registrationDate: Date;
public title: string = 'User Information';
public user: User;
public userId: string;
private unsubscribeSubject = new Subject<void>();
public constructor(
private changeDetectorRef: ChangeDetectorRef,
@Inject(MAT_DIALOG_DATA) public data: UserDetailDialogParams,
public dialogRef: MatDialogRef<GfUserDetailDialogComponent>
) {
this.userId = this.data.userId;
addIcons({ personOutline });
}
) {}
public ngOnInit() {
this.initialize();
@ -62,23 +55,12 @@ export class GfUserDetailDialogComponent implements OnDestroy, OnInit {
this.dialogRef.close();
}
private fetchUserDetails(): void {
this.isLoading = true;
// Use the user data passed from the admin users list if available
private fetchUserDetails() {
if (this.data.userData) {
this.userId = this.data.userData.id;
this.registrationDate = this.data.userData.createdAt;
this.isLoading = false;
this.changeDetectorRef.markForCheck();
} else {
// Fallback: use the user ID and set a placeholder registration date
this.userId = this.data.userId;
this.registrationDate = new Date(); // Placeholder
this.isLoading = false;
this.changeDetectorRef.markForCheck();
}
}
private initialize() {
this.fetchUserDetails();
}

18
apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html

@ -1,24 +1,28 @@
<gf-dialog-header
position="center"
[deviceType]="data.deviceType"
[title]="userId"
(closeButtonClicked)="onClose()"
/>
<div class="flex-grow-1" mat-dialog-content>
<div class="container p-0">
<div class="row">
<div class="col-12 mb-3">
<gf-value i18n size="medium">User Information</gf-value>
</div>
<div class="col-12 d-flex justify-content-center mb-3">
<gf-value i18n size="medium" [value]="title"></gf-value>
</div>
<div class="mb-3 row">
<div class="col-6 mb-3">
<gf-value i18n size="small" [value]="userId">User ID</gf-value>
<gf-value i18n size="medium" [value]="data.userData.id"
>User ID</gf-value
>
</div>
<div class="col-6 mb-3">
<gf-value i18n size="small" [value]="registrationDate | date: 'medium'"
<gf-value
i18n
size="medium"
[isDate]="true"
[locale]="user?.settings?.locale"
[value]="data.userData.createdAt"
>Registration Date</gf-value
>
</div>

Loading…
Cancel
Save