Refactor pagination logic and add error handling in history

Introduced `updatePageSize` for better page size management and added checks to prevent rapid page changes. Enhanced error handling in `history.component` with retry logic on failure. Implemented `RemoveTrailingPeriodPipe` for cleaner UI formatting.
This commit is contained in:
Teriuihi 2025-04-18 19:32:23 +02:00
parent 53f67a5075
commit 21f2b3e4a5
5 changed files with 60 additions and 8 deletions

View File

@ -48,7 +48,7 @@
</div> </div>
<div class="historyTable"> <div class="historyTable">
<app-history [userType]="userType" [punishmentType]="punishmentType" <app-history [userType]="userType" [punishmentType]="punishmentType"
[page]="page" [searchTerm]="finalSearchTerm" (pageChange)="pageSize = $event"> [page]="page" [searchTerm]="finalSearchTerm" (pageChange)="updatePageSize($event)">
</app-history> </app-history>
</div> </div>
<div class="changePageButtons"> <div class="changePageButtons">

View File

@ -40,13 +40,14 @@ export class BansComponent implements OnInit {
public finalSearchTerm: string = ''; public finalSearchTerm: string = '';
public searchTerm: string = ''; public searchTerm: string = '';
public filteredNames: string[] = []; public filteredNames: string[] = [];
public pageSize = 0; public pageSize = 10;
public historyCount: HistoryCount = { public historyCount: HistoryCount = {
bans: 0, bans: 0,
mutes: 0, mutes: 0,
kicks: 0, kicks: 0,
warnings: 0 warnings: 0
} }
private actualPage: number = 0;
ngOnInit() { ngOnInit() {
this.historyApi.getUserNames(this.userType, this.punishmentType).subscribe(names => { this.historyApi.getUserNames(this.userType, this.punishmentType).subscribe(names => {
@ -108,17 +109,21 @@ export class BansComponent implements OnInit {
if (this.page === this.getMaxPage()) { if (this.page === this.getMaxPage()) {
return; return;
} }
this.setPage(++this.page) this.setPage(this.page + 1)
} }
public previousPage() { public previousPage() {
if (this.page === 0) { if (this.page === 0) {
return; return;
} }
this.setPage(--this.page) this.setPage(this.page - 1)
} }
public setPage(page: number) { public setPage(page: number) {
if (this.actualPage !== this.page) {
console.warn('Changing page too quickly, the previous page change has not loaded yet');
return;
}
this.pushState(); this.pushState();
this.page = page this.page = page
} }
@ -159,4 +164,13 @@ export class BansComponent implements OnInit {
} }
return this.page !== compare; return this.page !== compare;
} }
public updatePageSize(pageSize: number) {
if (pageSize < 0) {
return;
} else {
this.pageSize = pageSize;
this.actualPage = this.page;
}
}
} }

View File

@ -34,7 +34,7 @@
<span>{{ entry.punishedBy }}</span> <span>{{ entry.punishedBy }}</span>
</div> </div>
</td> </td>
<td class="historyReason">{{ entry.reason }}</td> <td class="historyReason">{{ entry.reason | removeTrailingPeriod }}</td>
<td class="historyDate">{{ getPunishmentTime(entry) }}</td> <td class="historyDate">{{ getPunishmentTime(entry) }}</td>
<td class="historyDate">{{ getExpiredTime(entry) }}</td> <td class="historyDate">{{ getExpiredTime(entry) }}</td>
</tr> </tr>

View File

@ -1,15 +1,18 @@
import {Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core'; import {Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
import {BASE_PATH, HistoryService, PunishmentHistoryInner} from '../../../api'; import {BASE_PATH, HistoryService, PunishmentHistoryInner} from '../../../api';
import {map, Observable, shareReplay} from 'rxjs'; import {catchError, map, Observable, shareReplay} from 'rxjs';
import {NgForOf, NgIf, NgOptimizedImage} from '@angular/common'; import {NgForOf, NgIf, NgOptimizedImage} from '@angular/common';
import {CookieService} from 'ngx-cookie-service'; import {CookieService} from 'ngx-cookie-service';
import {RemoveTrailingPeriodPipe} from '../../util/RemoveTrailingPeriodPipe';
import {HttpErrorResponse} from '@angular/common/http';
@Component({ @Component({
selector: 'app-history', selector: 'app-history',
imports: [ imports: [
NgIf, NgIf,
NgForOf, NgForOf,
NgOptimizedImage NgOptimizedImage,
RemoveTrailingPeriodPipe
], ],
templateUrl: './history.component.html', templateUrl: './history.component.html',
styleUrl: './history.component.scss', styleUrl: './history.component.scss',
@ -36,7 +39,6 @@ export class HistoryComponent implements OnInit, OnChanges {
ngOnChanges(): void { ngOnChanges(): void {
this.reloadHistory(); this.reloadHistory();
this.pageChange.emit(this.history.length);
} }
ngOnInit(): void { ngOnInit(): void {
@ -57,6 +59,27 @@ export class HistoryComponent implements OnInit, OnChanges {
historyObservable.pipe( historyObservable.pipe(
map(history => { map(history => {
this.history = history; this.history = history;
this.pageChange.emit(this.history.length);
}),
catchError(err => {
this.pageChange.emit(-1);
let retrySeconds = 5;
if (err instanceof HttpErrorResponse) {
const headers = err.headers;
const retryAfterHeader = headers.get('Retry-After');
console.warn(err.error);
if (retryAfterHeader) {
const retryAfter = parseInt(retryAfterHeader || '0', 10);
if (!isNaN(retryAfter) && retryAfter > 0) {
retrySeconds = retryAfter + 1;
}
}
} else {
console.error(err);
}
setTimeout(() => this.reloadHistory(), retrySeconds * 1000);
return this.history;
}), }),
shareReplay(1) shareReplay(1)
).subscribe(); ).subscribe();

View File

@ -0,0 +1,15 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'removeTrailingPeriod',
standalone: true
})
export class RemoveTrailingPeriodPipe implements PipeTransform {
transform(value: string): string {
if (!value) {
return value;
}
return value.endsWith('.') ? value.slice(0, -1) : value;
}
}