From 46b4ea6b80eb3987553c74fb6d7dd57fe255d8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Buczek?= Date: Sat, 30 Nov 2024 11:37:31 +0100 Subject: [PATCH 1/4] fix: #183 set up auth status after deleting account --- .../user-account-settings/user-account-settings.component.ts | 4 +++- .../services/endpoints/game-record-endpoints.service.ts | 1 - src/app/shared/services/endpoints/user-endpoints.service.ts | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/components/sections/user-account-settings/user-account-settings.component.ts b/src/app/dashboard/components/sections/user-account-settings/user-account-settings.component.ts index 7d60893..41e239b 100644 --- a/src/app/dashboard/components/sections/user-account-settings/user-account-settings.component.ts +++ b/src/app/dashboard/components/sections/user-account-settings/user-account-settings.component.ts @@ -24,6 +24,7 @@ import { AuthEndpointsService } from '@endpoints/auth-endpoints.service'; import { ICourseResponse } from 'app/shared/models/course.models'; import { CourseEndpointsService } from '@endpoints/course-endpoints.service'; import { TRole } from 'app/shared/models/role.enum'; +import { AppStatusService } from 'app/shared/services/app-status.service'; @Component({ selector: 'app-user-account-settings', @@ -267,6 +268,7 @@ export class UserAccountSettingsComponent implements OnDestroy { private _authEndpointsService = inject(AuthEndpointsService); private _courseEndpointsService = inject(CourseEndpointsService); private _notificationService = inject(NotificationService); + private _appStatusService = inject(AppStatusService); private _router = inject(Router); private _getMeSubscription = new Subscription(); @@ -471,7 +473,7 @@ export class UserAccountSettingsComponent implements OnDestroy { .deleteAccount() .subscribe({ next: () => { - localStorage.removeItem('jwtToken'); + this._appStatusService.setAuthStatus(false); this._router.navigate(['']); this._notificationService.addNotification( 'Your account has been permamently deleted!' diff --git a/src/app/shared/services/endpoints/game-record-endpoints.service.ts b/src/app/shared/services/endpoints/game-record-endpoints.service.ts index 0257ccb..7a35fb9 100644 --- a/src/app/shared/services/endpoints/game-record-endpoints.service.ts +++ b/src/app/shared/services/endpoints/game-record-endpoints.service.ts @@ -40,7 +40,6 @@ export class GameRecordEndpointsService { if (sortBy) queryParams.append('sortBy', sortBy); if (sortDirection) queryParams.append('sortDirection', sortDirection); - console.log(queryParams.toString()); return this._httpClient .get( environment.backendApiUrl + `/api/GameRecord?${queryParams.toString()}`, diff --git a/src/app/shared/services/endpoints/user-endpoints.service.ts b/src/app/shared/services/endpoints/user-endpoints.service.ts index 520187a..0cd02b5 100644 --- a/src/app/shared/services/endpoints/user-endpoints.service.ts +++ b/src/app/shared/services/endpoints/user-endpoints.service.ts @@ -182,6 +182,7 @@ export class UserEndpointsService { .pipe( tap({ next: () => { + localStorage.removeItem('jwtToken'); console.log('Account deleted successfully'); }, }), From 6cfdc4f33e98ea4394f1452b5ccc3646bfdad25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Buczek?= Date: Sat, 30 Nov 2024 11:43:43 +0100 Subject: [PATCH 2/4] fix: #183 fixed bug with not loading recorded games data --- .../sections/recorded-games/recorded-games.component.ts | 2 +- src/app/dashboard/dashboard.page.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts b/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts index 8e08f91..b06076d 100644 --- a/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts +++ b/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts @@ -155,7 +155,7 @@ export class RecordedGamesComponent } public ngOnChanges(): void { - this.applyFilters(); + if (this.userId !== -1) this.applyFilters(); } public applyFilters(): void { diff --git a/src/app/dashboard/dashboard.page.component.ts b/src/app/dashboard/dashboard.page.component.ts index 0411df7..a610a1a 100644 --- a/src/app/dashboard/dashboard.page.component.ts +++ b/src/app/dashboard/dashboard.page.component.ts @@ -44,7 +44,7 @@ import { AuthRequiredDirective } from '@utils/directives/auth-required.directive class="flex flex-row justify-stretch w-full" />
From d233921dea81326c60069b19c6603eccb11c1a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Buczek?= Date: Sat, 30 Nov 2024 12:10:43 +0100 Subject: [PATCH 3/4] feat: #183 fixed sorting and loading bug in recorded games table --- .../recorded-games.component.ts | 23 +++++++++++-------- .../shared/recorded-game-table.component.ts | 15 +++--------- .../user-details/user-details.component.ts | 23 +++++++++++-------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts b/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts index b06076d..f03eb1d 100644 --- a/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts +++ b/src/app/dashboard/components/sections/recorded-games/recorded-games.component.ts @@ -87,15 +87,15 @@ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
- @if (recordedGamesData && recordedGamesData.length > 0) { - - } @else { + + @if (!isLoading && recordedGamesData && recordedGamesData.length === 0) { No records found. } @if (errorMessage !== null) { @@ -120,6 +120,7 @@ export class RecordedGamesComponent public avalaibleGamesList: IGameResponse[] = []; public recordedGamesData: IRecordedGameResponse[] | null = null; + public isLoading = false; public errorMessage: string | null = null; public filterForm!: FormGroup; @@ -159,6 +160,7 @@ export class RecordedGamesComponent } public applyFilters(): void { + this.isLoading = true; const filters = this.filterForm.value; this._getRecordedGamesSubscription = this._gameRecordEndpointsService .getAllRecordedGames( @@ -174,9 +176,12 @@ export class RecordedGamesComponent next: response => { this.recordedGamesData = response; this.errorMessage = null; + this.isLoading = false; }, error: (error: string) => { + this.recordedGamesData = null; this.errorMessage = error; + this.isLoading = false; }, }); } diff --git a/src/app/dashboard/components/shared/recorded-game-table.component.ts b/src/app/dashboard/components/shared/recorded-game-table.component.ts index 4c9aa30..621b4a8 100644 --- a/src/app/dashboard/components/shared/recorded-game-table.component.ts +++ b/src/app/dashboard/components/shared/recorded-game-table.component.ts @@ -15,7 +15,7 @@ import { LoadingSpinnerComponent } from '../../../shared/components/common/loadi standalone: true, imports: [CommonModule, LoadingSpinnerComponent], template: ` - @if (isLoadingNeeded) { + @if (isLoading) { } @else { @if (recordedGamesData && recordedGamesData.length > 0) { @@ -106,17 +106,16 @@ import { LoadingSpinnerComponent } from '../../../shared/components/common/loadi } `, }) -export class RecordedGameTableComponent implements OnChanges { +export class RecordedGameTableComponent { @Input({ required: true }) public recordedGamesData: | IRecordedGameResponse[] | null = null; + @Input({ required: true }) public isLoading = false; @Output() public downloadEmitter = new EventEmitter(); @Output() public deleteEmitter = new EventEmitter(); @Output() public sortByEmitter = new EventEmitter<'Ended' | 'SizeMb'>(); @Output() public sortDirectionEmitter = new EventEmitter<'Asc' | 'Desc'>(); - public isLoadingNeeded = true; - public sortBy: 'Ended' | 'SizeMb' = 'Ended'; public sortDirection: 'Asc' | 'Desc' = 'Asc'; @@ -130,12 +129,4 @@ export class RecordedGameTableComponent implements OnChanges { this.sortByEmitter.emit(this.sortBy); this.sortDirectionEmitter.emit(this.sortDirection); } - - public ngOnChanges(): void { - if (this.recordedGamesData === null) { - this.isLoadingNeeded = true; - } else { - this.isLoadingNeeded = false; - } - } } diff --git a/src/app/dashboard/user-details/user-details.component.ts b/src/app/dashboard/user-details/user-details.component.ts index dd9a86a..404b2a0 100644 --- a/src/app/dashboard/user-details/user-details.component.ts +++ b/src/app/dashboard/user-details/user-details.component.ts @@ -116,15 +116,15 @@ import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; - @if (recordedGamesData && recordedGamesData.length > 0) { - - } @else { + + @if (!isLoading && recordedGamesData && recordedGamesData.length === 0) { No records found. } @if (errorMessage !== null) { @@ -152,6 +152,7 @@ export class UserDetailsComponent public avalaibleGamesList: IGameResponse[] = []; public recordedGamesData: IRecordedGameResponse[] | null = null; + public isLoading = false; public errorMessage: string | null = null; public filterForm!: FormGroup; @@ -223,6 +224,7 @@ export class UserDetailsComponent } public applyFilters(): void { + this.isLoading = true; const filters = this.filterForm.value; this._getRecordedGamesSubscription = this._gameRecordEndpointsService .getAllRecordedGames( @@ -238,9 +240,12 @@ export class UserDetailsComponent next: response => { this.recordedGamesData = response; this.errorMessage = null; + this.isLoading = false; }, error: (error: string) => { + this.recordedGamesData = null; this.errorMessage = error; + this.isLoading = false; }, }); } From 119e7e17207d3c762bccea6385da55d7e66cb45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Buczek?= Date: Sat, 30 Nov 2024 12:19:54 +0100 Subject: [PATCH 4/4] feat: #183 added loading spinner to users table --- .../admin-settings.component.ts | 6 + .../components/shared/user-table.component.ts | 320 +++++++++--------- 2 files changed, 171 insertions(+), 155 deletions(-) diff --git a/src/app/dashboard/components/sections/admin-settings/admin-settings.component.ts b/src/app/dashboard/components/sections/admin-settings/admin-settings.component.ts index c712d35..c88eb9a 100644 --- a/src/app/dashboard/components/sections/admin-settings/admin-settings.component.ts +++ b/src/app/dashboard/components/sections/admin-settings/admin-settings.component.ts @@ -117,6 +117,7 @@ import { ICourseResponse } from 'app/shared/models/course.models'; @@ -142,6 +143,7 @@ export class AdminSettingsComponent public filterForm!: FormGroup; public filteredUsers: IUserResponse[] | null = null; + public isLoading = false; public avalaibleCourses: ICourseResponse[] = []; public errorMessage: string | null = null; @@ -214,6 +216,7 @@ export class AdminSettingsComponent } public applyFilters(): void { + this.isLoading = true; const filters = this.filterForm.value; this._getUsersSubscription = this._adminEndpointsService .getUsers( @@ -233,10 +236,13 @@ export class AdminSettingsComponent .subscribe({ next: (response: IUserResponse[]) => { this.filteredUsers = response; + this.errorMessage = null; + this.isLoading = false; }, error: error => { this.filteredUsers = null; this.errorMessage = error; + this.isLoading = false; }, }); } diff --git a/src/app/dashboard/components/shared/user-table.component.ts b/src/app/dashboard/components/shared/user-table.component.ts index a23eb2f..83f155a 100644 --- a/src/app/dashboard/components/shared/user-table.component.ts +++ b/src/app/dashboard/components/shared/user-table.component.ts @@ -16,180 +16,189 @@ import { TRole } from 'app/shared/models/role.enum'; import { IUserResponse } from 'app/shared/models/user.models'; import { NotificationService } from 'app/shared/services/notification.service'; import { Subscription } from 'rxjs'; +import { LoadingSpinnerComponent } from '../../../shared/components/common/loading-spinner.component'; @Component({ selector: 'app-user-table', standalone: true, - imports: [RouterLink, AllowedRolesDirective], + imports: [RouterLink, AllowedRolesDirective, LoadingSpinnerComponent], template: ` - @if (filteredUsers && filteredUsers.length > 0) { -
-
+ @if (isLoading) { + + } @else { + @if (filteredUsers && filteredUsers.length > 0) { +
- No. -
- - @if (sortBy === 'Email') { - - - - } @else { - - - - } -
-
- - @if (sortBy === 'StudyYearCycleA') { - - - - } @else { - - - - } -
-
- - @if (sortBy === 'CourseName') { - - - - } @else { - - - - } -
-
- - @if (sortBy === 'Group') { - - - - } @else { - - - - } -
- Role - Ban status - Details -
- @for (user of filteredUsers; track user.id) { + class="flex flex-col min-w-[66rem] w-full justify-around space-y-0 font-mono">
- {{ $index + 1 }}. - {{ user.email }} - {{ user.studyCycleYearA }}/{{ user.studyCycleYearB }} - {{ - user?.course?.name - }} - {{ user.group }} + class="flex flex-row space-x-4 justify-between bg-mainGray text-mainOrange text-sm xs:text-base font-bold px-4 py-2"> + No.
- - {{ user.role }} - - + @if (sortBy === 'Email') { + + + + } @else { + + + + } +
+
+ + @if (sortBy === 'StudyYearCycleA') { + + + + } @else { + + + + } +
+
+ + @if (sortBy === 'CourseName') { + + + + } @else { + + + + } +
+
+ + @if (sortBy === 'Group') { + + + + } @else { + + + + } +
+ Role + Ban status + Details +
+ @for (user of filteredUsers; track user.id) { +
+ {{ $index + 1 }}. + {{ user.email }} + {{ user.studyCycleYearA }}/{{ user.studyCycleYearB }} + {{ + user?.course?.name + }} + {{ user.group }}
- + class="flex flex-row gap-x-2 items-center justify-center w-2/12"> + + {{ user.role }} + +
+ + +
-
-
- {{ user.banned ? 'BANNED' : 'NOT BANNED' }} -
+ class="flex flex-row gap-x-2 items-center justify-center w-2/12"> + {{ user.banned ? 'BANNED' : 'NOT BANNED' }} +
+ +
+ + + + +
- - - - - -
- } + } +
- - } @else { - No users found. + } @else { + No users found. + } }
@if (errorMessage !== null) { @@ -201,6 +210,7 @@ import { Subscription } from 'rxjs'; export class UserTableComponent implements OnChanges, OnDestroy { @Input({ required: true }) public filteredUsers: IUserResponse[] | null = null; + @Input({ required: true }) public isLoading = false; @Output() public sortByEmitter = new EventEmitter< | 'Id' | 'Email'