From 642a439f21a92dd0be1e580fbfa2435675a19420 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Fri, 27 Jun 2025 09:36:56 +0200 Subject: [PATCH 1/2] Updated trace and fixed status global --- .../global-status/global-status.component.ts | 9 ++ .../status-tab/status-tab.component.html | 8 +- .../task-logs/task-logs.component.css | 84 ++++++++++++++++++- .../task-logs/task-logs.component.html | 43 ++++++++-- .../task-logs/task-logs.component.ts | 74 +++++++++++++++- .../src/app/layout/header/header.component.ts | 2 +- 6 files changed, 200 insertions(+), 20 deletions(-) diff --git a/ogWebconsole/src/app/components/global-status/global-status.component.ts b/ogWebconsole/src/app/components/global-status/global-status.component.ts index b6e27ca..6b6e6d9 100644 --- a/ogWebconsole/src/app/components/global-status/global-status.component.ts +++ b/ogWebconsole/src/app/components/global-status/global-status.component.ts @@ -44,6 +44,14 @@ export class GlobalStatusComponent implements OnInit { isDhcp: boolean = false; isRepository: boolean = false; + // Loading específicos para cada sección + loadingOgBootOgLives: boolean = false; + loadingOgBootServices: boolean = false; + loadingOgBootDisk: boolean = false; + loadingDhcpSubnets: boolean = false; + loadingDhcpServices: boolean = false; + loadingDhcpDisk: boolean = false; + constructor( private configService: ConfigService, private toastService: ToastrService, @@ -160,6 +168,7 @@ export class GlobalStatusComponent implements OnInit { if (data.message.installed_oglives) { installedOgLives.push(...data.message.installed_oglives); } + this.loadingOgBootOgLives = false; } diskUsageChartData.length = 0; diff --git a/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.html b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.html index 82bd90d..eb34459 100644 --- a/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.html +++ b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.html @@ -2,7 +2,7 @@
-
+
@@ -32,7 +32,7 @@
{{ 'usedPercentageLabel' | translate }}: - {{ isRepository ? diskUsage.used_percentage : diskUsage.percentage }} + {{ isRepository ? diskUsage.used_percentage : diskUsage.percentage }}%
@@ -67,7 +67,7 @@
{{ 'usedPercentageLabel' | translate }}: - {{ ramUsage.used_percentage }} + {{ ramUsage.used_percentage }}%
@@ -84,7 +84,7 @@
-
{{ cpuUsage.used_percentage }}
+
{{ cpuUsage.used_percentage }}%
Uso actual
diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.css b/ogWebconsole/src/app/components/task-logs/task-logs.component.css index 127ad84..42be1ad 100644 --- a/ogWebconsole/src/app/components/task-logs/task-logs.component.css +++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.css @@ -73,9 +73,60 @@ border-left: 4px solid #667eea; } -.stat-card:hover { +.stat-card.clickable { + cursor: pointer; + position: relative; + overflow: hidden; +} + +.stat-card.clickable::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); + transition: left 0.5s ease; +} + +.stat-card.clickable:hover::before { + left: 100%; +} + +.stat-card.clickable:hover { + transform: translateY(-3px); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); +} + +.stat-card.clickable:active { + transform: translateY(-1px); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); +} + +.stat-card.active-filter { transform: translateY(-2px); - box-shadow: 0 8px 15px rgba(0, 0, 0, 0.15); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25); + border: 2px solid #fff; + position: relative; +} + +.stat-card.active-filter::after { + content: '✓'; + position: absolute; + top: 8px; + right: 8px; + background: rgba(255, 255, 255, 0.9); + color: #28a745; + border-radius: 50%; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; + font-size: 12px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .stat-total { @@ -161,6 +212,35 @@ margin-bottom: 15px; } +.filters-header-actions { + display: flex; + align-items: center; + gap: 15px; +} + +.active-filter-indicator { + display: flex; + align-items: center; + gap: 8px; + background: #e3f2fd; + color: #1976d2; + padding: 8px 12px; + border-radius: 20px; + font-size: 0.9rem; + font-weight: 500; + border: 1px solid #bbdefb; +} + +.active-filter-indicator mat-icon { + font-size: 18px; + width: 18px; + height: 18px; +} + +.active-filter-indicator button { + margin-left: 4px; +} + .filters-header h3 { margin: 0; color: #495057; diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.html b/ogWebconsole/src/app/components/task-logs/task-logs.component.html index 39ca165..7aeea14 100644 --- a/ogWebconsole/src/app/components/task-logs/task-logs.component.html +++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.html @@ -22,23 +22,38 @@
-
+
{{ totalStats.total }}
{{ 'totalTraces' | translate }}
-
+
{{ getStatusCount('today') }}
{{ 'todayTraces' | translate }}
-
+
{{ getStatusCount('success') }}
{{ 'successful' | translate }}
-
+
{{ getStatusCount('failed') }}
{{ 'failed' | translate }}
-
+
{{ getStatusCount('in-progress') }}
{{ 'inProgress' | translate }}
@@ -47,10 +62,20 @@

{{ 'filters' | translate }}

- +
+
+ filter_alt + Filtro activo: {{ getActiveFilterLabel() }} + +
+ +
diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts index 5386f4d..5e3e13a 100644 --- a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts +++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts @@ -113,6 +113,7 @@ export class TaskLogsComponent implements OnInit, OnDestroy { clientControl = new FormControl(); filteredCommands!: Observable; commandControl = new FormControl(); + activeFilter: string = ''; constructor(private http: HttpClient, private joyrideService: JoyrideService, @@ -214,7 +215,7 @@ export class TaskLogsComponent implements OnInit, OnDestroy { const today = new Date(); const todayString = this.datePipe.transform(today, 'yyyy-MM-dd'); return this.traces.filter(trace => - trace.executedAt && trace.executedAt.startsWith(todayString) + trace.executedAt && todayString && trace.executedAt.startsWith(todayString) ).length; } @@ -461,7 +462,9 @@ export class TaskLogsComponent implements OnInit, OnDestroy { const totalRequest = this.http.get(`${this.baseUrl}/traces?page=1&itemsPerPage=1`); const todayString = this.datePipe.transform(new Date(), 'yyyy-MM-dd'); - const todayRequest = this.http.get(`${this.baseUrl}/traces?executedAt[after]=${todayString}&page=1&itemsPerPage=1`); + const todayRequest = todayString ? + this.http.get(`${this.baseUrl}/traces?executedAt[after]=${todayString}&page=1&itemsPerPage=1`) : + this.http.get(`${this.baseUrl}/traces?page=1&itemsPerPage=1`); forkJoin([totalRequest, ...requests, todayRequest]).subscribe( (responses) => { @@ -489,7 +492,7 @@ export class TaskLogsComponent implements OnInit, OnDestroy { pending: this.traces.filter(trace => trace.status === 'pending').length, inProgress: this.traces.filter(trace => trace.status === 'in-progress').length, cancelled: this.traces.filter(trace => trace.status === 'cancelled').length, - today: this.traces.filter(trace => trace.executedAt && trace.executedAt.startsWith(todayString)).length + today: this.traces.filter(trace => trace.executedAt && todayString && trace.executedAt.startsWith(todayString)).length }; } ); @@ -501,6 +504,7 @@ export class TaskLogsComponent implements OnInit, OnDestroy { clientSearchStatusInput.value = null; clientSearchClientInput.value = null; this.filters = {}; + this.activeFilter = ''; this.loadTraces(); } @@ -583,7 +587,6 @@ export class TaskLogsComponent implements OnInit, OnDestroy { }); } - // Métodos para paginación getPaginationFrom(): number { return (this.page * this.itemsPerPage) + 1; } @@ -595,4 +598,67 @@ export class TaskLogsComponent implements OnInit, OnDestroy { getPaginationTotal(): number { return this.length; } + + filterByTotal(): void { + this.resetAllFilters(); + this.activeFilter = 'total'; + this.loadTraces(); + } + + filterByToday(): void { + this.resetAllFilters(); + const todayString = this.datePipe.transform(new Date(), 'yyyy-MM-dd'); + if (todayString) { + this.filters['executedAt[after]'] = todayString; + } + this.activeFilter = 'today'; + this.loadTraces(); + } + + filterBySuccess(): void { + this.resetAllFilters(); + this.filters['status'] = 'success'; + this.activeFilter = 'success'; + this.loadTraces(); + } + + filterByFailed(): void { + this.resetAllFilters(); + this.filters['status'] = 'failed'; + this.activeFilter = 'failed'; + this.loadTraces(); + } + + filterByInProgress(): void { + this.resetAllFilters(); + this.filters['status'] = 'in-progress'; + this.activeFilter = 'in-progress'; + this.loadTraces(); + } + + isFilterActive(filterType: string): boolean { + return this.activeFilter === filterType; + } + + getActiveFilterLabel(): string { + switch(this.activeFilter) { + case 'total': + return 'Todas las trazas'; + case 'today': + return 'Trazas de hoy'; + case 'success': + return 'Trazas exitosas'; + case 'failed': + return 'Trazas fallidas'; + case 'in-progress': + return 'Trazas en progreso'; + default: + return ''; + } + } + + private resetAllFilters(): void { + this.filters = {}; + this.activeFilter = ''; + } } diff --git a/ogWebconsole/src/app/layout/header/header.component.ts b/ogWebconsole/src/app/layout/header/header.component.ts index 20ef4e2..f3e6c81 100644 --- a/ogWebconsole/src/app/layout/header/header.component.ts +++ b/ogWebconsole/src/app/layout/header/header.component.ts @@ -42,7 +42,7 @@ export class HeaderComponent implements OnInit { showGlobalStatus() { this.dialog.open(GlobalStatusComponent, { - width: '5vw', + width: '65vw', height: '80vh', }) } -- 2.40.1 From 01390a1fab43035bd9a368ce0c6dee785363be8d Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Fri, 27 Jun 2025 09:57:34 +0200 Subject: [PATCH 2/2] Updated trace filters and added logs in real time --- .../task-logs/task-logs.component.css | 24 +++++++++++++++++-- .../task-logs/task-logs.component.html | 12 ++++++---- .../task-logs/task-logs.component.ts | 9 +++++++ 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.css b/ogWebconsole/src/app/components/task-logs/task-logs.component.css index 42be1ad..2d6c886 100644 --- a/ogWebconsole/src/app/components/task-logs/task-logs.component.css +++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.css @@ -377,8 +377,28 @@ table { } .command-id, .client-ip { - font-size: 0.75rem; - color: #6c757d; + font-size: 0.8rem; + color: #666; + font-family: monospace; +} + +.clickable-job-id { + cursor: pointer; + color: #1976d2 !important; + text-decoration: underline; + transition: all 0.2s ease; +} + +.clickable-job-id:hover { + color: #1565c0 !important; + text-decoration: none; + background-color: rgba(25, 118, 210, 0.1); + padding: 2px 4px; + border-radius: 4px; +} + +.clickable-job-id:active { + transform: scale(0.98); } .date-time { diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.html b/ogWebconsole/src/app/components/task-logs/task-logs.component.html index 7aeea14..e5cbd38 100644 --- a/ogWebconsole/src/app/components/task-logs/task-logs.component.html +++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.html @@ -254,7 +254,12 @@
{{ translateCommand(trace.command) }} - {{ trace.jobId }} + + {{ trace.jobId }} +
@@ -303,10 +308,7 @@ info - +
diff --git a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts index 5e3e13a..3fc1698 100644 --- a/ogWebconsole/src/app/components/task-logs/task-logs.component.ts +++ b/ogWebconsole/src/app/components/task-logs/task-logs.component.ts @@ -382,6 +382,15 @@ export class TaskLogsComponent implements OnInit, OnDestroy { }); } + openLogsInNewTab(trace: any): void { + if (trace.client?.ip) { + const logsUrl = `${this.baseUrl}/pcclients/${trace.client.ip}/cgi-bin/httpd-log.sh`; + window.open(logsUrl, '_blank'); + } else { + this.toastService.error('No se puede acceder a los logs: IP del cliente no disponible', 'Error'); + } + } + loadTraces(): void { this.loading = true; const url = `${this.baseUrl}/traces?page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}`; -- 2.40.1