Added polling into disk logs
parent
e7eb7c59c1
commit
8060962b8a
|
|
@ -95,6 +95,34 @@
|
|||
word-break: break-all;
|
||||
}
|
||||
|
||||
.live-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
margin-left: 10px;
|
||||
padding: 2px 8px;
|
||||
background-color: #d32f2f;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.05em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.live-dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
animation: blink 1s step-start infinite;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0; }
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
padding: 16px 24px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,18 @@
|
|||
<h2 mat-dialog-title>
|
||||
<mat-icon>storage</mat-icon>
|
||||
{{ 'diskLogs' | translate }} - {{ data.client.name }}
|
||||
<span *ngIf="isLive" class="live-badge">
|
||||
<span class="live-dot"></span>LIVE
|
||||
</span>
|
||||
</h2>
|
||||
<div class="header-actions">
|
||||
<button mat-icon-button (click)="loadLogs()" [matTooltip]="'buttonRefresh' | translate" [disabled]="loading">
|
||||
<button mat-icon-button
|
||||
(click)="toggleLive()"
|
||||
[matTooltip]="(isLive ? 'diskLogsStopLive' : 'diskLogsStartLive') | translate"
|
||||
[color]="isLive ? 'warn' : ''">
|
||||
<mat-icon>{{ isLive ? 'pause_circle' : 'play_circle' }}</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="loadLogs()" [matTooltip]="'buttonRefresh' | translate" [disabled]="loading || isLive">
|
||||
<mat-icon>refresh</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -27,7 +36,7 @@
|
|||
<span>{{ error }}</span>
|
||||
</div>
|
||||
|
||||
<pre *ngIf="!loading && !error" class="log-content">{{ content || ('noLogsAvailable' | translate) }}</pre>
|
||||
<pre *ngIf="!loading && !error" class="log-content" #logContent>{{ content || ('noLogsAvailable' | translate) }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, Inject, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
|
|
@ -12,7 +12,14 @@ export class ClientDiskLogsModalComponent implements OnInit, OnDestroy {
|
|||
content: string = '';
|
||||
loading: boolean = false;
|
||||
error: string | null = null;
|
||||
isLive: boolean = false;
|
||||
|
||||
private apiUrl: string;
|
||||
private pollInterval: ReturnType<typeof setInterval> | null = null;
|
||||
private readonly POLL_INTERVAL_MS = 3000;
|
||||
private readonly LIVE_LINES = 200;
|
||||
|
||||
@ViewChild('logContent') logContent!: ElementRef<HTMLPreElement>;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<ClientDiskLogsModalComponent>,
|
||||
|
|
@ -27,26 +34,67 @@ export class ClientDiskLogsModalComponent implements OnInit, OnDestroy {
|
|||
this.loadLogs();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {}
|
||||
ngOnDestroy(): void {
|
||||
this.stopLive();
|
||||
}
|
||||
|
||||
loadLogs(): void {
|
||||
loadLogs(lines: number = 0): void {
|
||||
this.loading = true;
|
||||
this.error = null;
|
||||
|
||||
this.http.get<{ content: string }>(`${this.apiUrl}/clients/${this.data.client.uuid}/disk-logs`).subscribe({
|
||||
const url = lines > 0
|
||||
? `${this.apiUrl}/clients/${this.data.client.uuid}/disk-logs?lines=${lines}`
|
||||
: `${this.apiUrl}/clients/${this.data.client.uuid}/disk-logs`;
|
||||
|
||||
this.http.get<{ content: string }>(url).subscribe({
|
||||
next: (response) => {
|
||||
this.content = response.content || '';
|
||||
this.loading = false;
|
||||
if (this.isLive) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
this.error = err.status === 404
|
||||
? 'No se encontró el archivo de logs para este cliente.'
|
||||
: 'Error al obtener los logs de disco.';
|
||||
this.loading = false;
|
||||
this.stopLive();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleLive(): void {
|
||||
if (this.isLive) {
|
||||
this.stopLive();
|
||||
} else {
|
||||
this.startLive();
|
||||
}
|
||||
}
|
||||
|
||||
private startLive(): void {
|
||||
this.isLive = true;
|
||||
this.loadLogs(this.LIVE_LINES);
|
||||
this.pollInterval = setInterval(() => this.loadLogs(this.LIVE_LINES), this.POLL_INTERVAL_MS);
|
||||
}
|
||||
|
||||
private stopLive(): void {
|
||||
this.isLive = false;
|
||||
if (this.pollInterval !== null) {
|
||||
clearInterval(this.pollInterval);
|
||||
this.pollInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
private scrollToBottom(): void {
|
||||
setTimeout(() => {
|
||||
const el = this.logContent?.nativeElement;
|
||||
if (el) {
|
||||
el.scrollTop = el.scrollHeight;
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
||||
closeModal(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,6 +232,8 @@
|
|||
"clientListPartition": "List of clients where partitioning will be performed",
|
||||
"clientLogs": "Client Logs",
|
||||
"diskLogs": "Disk Logs",
|
||||
"diskLogsStartLive": "Enable real-time mode",
|
||||
"diskLogsStopLive": "Stop real-time mode",
|
||||
"clientMacOS": "MacOS client",
|
||||
"clientOff": "Client off",
|
||||
"clientOgLive": "OGLive client",
|
||||
|
|
|
|||
|
|
@ -232,6 +232,8 @@
|
|||
"clientListPartition": "Listado de clientes donde se realizará el particionado",
|
||||
"clientLogs": "Logs de cliente",
|
||||
"diskLogs": "Logs de disco",
|
||||
"diskLogsStartLive": "Activar modo en tiempo real",
|
||||
"diskLogsStopLive": "Detener modo en tiempo real",
|
||||
"clientMacOS": "Cliente MacOS",
|
||||
"clientOff": "Cliente apagado",
|
||||
"clientOgLive": "Cliente OGLive",
|
||||
|
|
|
|||
Loading…
Reference in New Issue