import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { GridModule, PageChangeEvent } from '@progress/kendo-angular-grid'; import { ButtonsModule } from '@progress/kendo-angular-buttons'; import { DropDownsModule } from '@progress/kendo-angular-dropdowns'; import { InputsModule } from '@progress/kendo-angular-inputs'; import { DateInputsModule } from '@progress/kendo-angular-dateinputs'; import { DialogsModule } from '@progress/kendo-angular-dialog'; import { AUDIT_CATEGORY_OPTIONS, LOG_LEVEL_OPTIONS } from '../../../../shared/i18n/option-lists'; import { LoggingApiService } from '../../services/logging-api.service'; import { AuditLogListItem, AuditLogDetail, AuditLogQuery } from '../../models/logging.model'; @Component({ selector: 'app-audit-logs-page', standalone: true, imports: [ CommonModule, FormsModule, GridModule, ButtonsModule, DropDownsModule, InputsModule, DateInputsModule, DialogsModule, ], templateUrl: './audit-logs-page.component.html', styleUrls: ['./audit-logs-page.component.scss'], }) export class AuditLogsPageComponent implements OnInit { rows: AuditLogListItem[] = []; total = 0; page = 1; pageSize = 20; loading = false; readonly categories = AUDIT_CATEGORY_OPTIONS; readonly levels = LOG_LEVEL_OPTIONS; actions: { value: string; label: string }[] = []; category: string | null = null; action: string | null = null; search = ''; from: Date | null = null; to: Date | null = null; detail: AuditLogDetail | null = null; detailChanges = ''; constructor(private api: LoggingApiService) {} ngOnInit(): void { this.api.getAuditCatalog().subscribe(c => { this.actions = c.actions.map(a => ({ value: a, label: a })); }); this.load(); } load(): void { this.loading = true; const query: AuditLogQuery = { page: this.page, pageSize: this.pageSize, category: this.category ?? undefined, action: this.action ?? undefined, search: this.search || undefined, from: this.toLocalDate(this.from), to: this.toLocalDate(this.to), }; this.api.getAuditLogs(query).subscribe({ next: r => { this.rows = r.items; this.total = r.totalCount; this.loading = false; }, error: () => (this.loading = false), }); } get skip(): number { return (this.page - 1) * this.pageSize; } applyFilter(): void { this.page = 1; this.load(); } onPageChange(e: PageChangeEvent): void { this.page = Math.floor(e.skip / this.pageSize) + 1; this.load(); } view(row: AuditLogListItem): void { this.api.getAuditLog(row.id).subscribe(d => { this.detail = d; this.detailChanges = this.prettyJson(d.changes); }); } levelClass(level: string): string { return 'log-level log-level--' + level.toLowerCase(); } /** Pretty-print the stored Changes JSON; fall back to the raw string if it isn't JSON. */ private prettyJson(raw: string | null | undefined): string { if (!raw) return ''; try { return JSON.stringify(JSON.parse(raw), null, 2); } catch { return raw; } } private toLocalDate(d: Date | null): string | undefined { if (!d) return undefined; const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, '0'); const day = String(d.getDate()).padStart(2, '0'); return `${y}-${m}-${day}`; } }