101 lines
3.4 KiB
TypeScript
101 lines
3.4 KiB
TypeScript
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}`;
|
|
}
|
|
}
|