diff --git a/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.css b/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.css
index 974fbb6..637a776 100644
--- a/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.css
+++ b/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.css
@@ -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;
diff --git a/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.html b/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.html
index d1288db..30489d8 100644
--- a/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.html
+++ b/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.html
@@ -3,9 +3,18 @@
storage
{{ 'diskLogs' | translate }} - {{ data.client.name }}
+
+ LIVE
+
@@ -27,7 +36,7 @@
{{ error }}
- {{ content || ('noLogsAvailable' | translate) }}
+ {{ content || ('noLogsAvailable' | translate) }}
diff --git a/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.ts b/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.ts
index 884adaf..aa1f5bb 100644
--- a/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.ts
+++ b/ogWebconsole/src/app/components/groups/shared/client-disk-logs-modal/client-disk-logs-modal.component.ts
@@ -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 | null = null;
+ private readonly POLL_INTERVAL_MS = 3000;
+ private readonly LIVE_LINES = 200;
+
+ @ViewChild('logContent') logContent!: ElementRef;
constructor(
public dialogRef: MatDialogRef,
@@ -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();
}
diff --git a/ogWebconsole/src/locale/en.json b/ogWebconsole/src/locale/en.json
index 558716d..3e2cd7f 100644
--- a/ogWebconsole/src/locale/en.json
+++ b/ogWebconsole/src/locale/en.json
@@ -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",
diff --git a/ogWebconsole/src/locale/es.json b/ogWebconsole/src/locale/es.json
index d14ecd4..b2ce53e 100644
--- a/ogWebconsole/src/locale/es.json
+++ b/ogWebconsole/src/locale/es.json
@@ -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",