import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators, } from '@angular/forms'; import { NgSelectModule } from '@ng-select/ng-select'; import { TranslateModule } from '@ngx-translate/core'; import { LOGGING_DETAILS_FILE_NAME, pageSizeOptions, toDateAfterFromDateValidator, } from '../utils/app.constants'; import { CommonModule, DatePipe } from '@angular/common'; import { HttpParams } from '@angular/common/http'; import { URIKey } from '../utils/uri-enums'; import { HttpURIService } from '../app.http.uri.service'; import { LogsManagementResponse } from '../utils/app.interfaces'; import { ExcelExportService } from '../shared/services/excel-export.service'; @Component({ selector: 'app-logging', standalone: true, imports: [ TranslateModule, FormsModule, NgSelectModule, CommonModule, ReactiveFormsModule, ], providers: [DatePipe], templateUrl: './logging.component.html', styleUrl: './logging.component.scss', }) export class LoggingComponent implements OnInit { logsSearchForm!: FormGroup; pageSizeOptions = pageSizeOptions; itemsPerPage = 10; currentPage = 1; maxDate: string; searchText = ''; logsDataExpanded = true; isLoading = false; /** DATA LAYERS (do not mix these) */ allItems: LogsManagementResponse[] = []; // raw API data filteredItems: LogsManagementResponse[] = []; // after search pagedItems: LogsManagementResponse[] = []; // table view constructor( private fb: FormBuilder, private httpService: HttpURIService, private datePipe: DatePipe, private excelExportService: ExcelExportService, ) { this.maxDate = new Date().toISOString().split('T')[0]; } ngOnInit(): void { this.logsSearchForm = this.fb.group( { fromDate: ['', Validators.required], toDate: ['', Validators.required], }, { validators: toDateAfterFromDateValidator }, ); } getlogsData(): void { if (this.logsSearchForm.invalid) return; this.isLoading = true; const { fromDate, toDate } = this.logsSearchForm.value; const params = new HttpParams() .set('fromDate', this.datePipe.transform(fromDate, 'dd-MM-yyyy')!) .set('toDate', this.datePipe.transform(toDate, 'dd-MM-yyyy')!); this.httpService .requestGET(URIKey.LOGGER_MANAGER_URI, params) .subscribe({ next: (response) => { this.allItems = response ?? []; this.filteredItems = [...this.allItems]; this.currentPage = 1; this.updatePagedItems(); this.isLoading = false; }, error: () => { this.allItems = []; this.filteredItems = []; this.pagedItems = []; this.isLoading = false; }, }); } /** SEARCH — filters DATA, not DOM */ applySearch(): void { const value = this.searchText.toLowerCase().trim(); if (!value) { this.filteredItems = [...this.allItems]; } else { this.filteredItems = this.allItems.filter((item) => [ 'id', 'method', 'remoteIp', 'requestUri', 'responseCode', 'userId', 'dateTime', ].some((key) => String((item as any)[key] ?? '') .toLowerCase() .includes(value), ), ); } this.currentPage = 1; this.updatePagedItems(); } updatePagedItems(): void { const start = (this.currentPage - 1) * this.itemsPerPage; const end = start + this.itemsPerPage; this.pagedItems = this.filteredItems.slice(start, end); } totalPages(): number { return Math.ceil(this.filteredItems.length / this.itemsPerPage); } previousPage(): void { if (this.currentPage > 1) { this.currentPage--; this.updatePagedItems(); } } nextPage(): void { if (this.currentPage < this.totalPages()) { this.currentPage++; this.updatePagedItems(); } } itemsPerPageChanged(): void { this.currentPage = 1; this.updatePagedItems(); } toggleTableCard(): void { this.logsDataExpanded = !this.logsDataExpanded; } exportDataInExcel(): void { const sanitizedData = this.filteredItems.map(item => { if (item.requestBody) { try { const body = JSON.parse(item.requestBody); if (body.password) { body.password = '******'; } return { ...item, requestBody: JSON.stringify(body) }; } catch { return item; } } return item; }); this.excelExportService.exportExcel( sanitizedData, LOGGING_DETAILS_FILE_NAME, ); } }