From 4788e1f7bc555eff57687b99161c1bf38d67c706 Mon Sep 17 00:00:00 2001 From: jmbardallo Date: Fri, 30 Oct 2026 15:09:57 +0100 Subject: [PATCH] fix(plugins): sincronizacion reciproca de tiempo restante y auto-conexion mercure (v1.24.3) --- CHANGELOG.md | 9 +++++++++ ogWebconsole/package.json | 2 +- .../app/components/groups/groups.component.ts | 10 +++++++++- .../src/app/services/plugin.service.ts | 18 ++++++++++++++++-- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a4417e..ef85e8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [1.24.3] - 2026-10-30 + +### Fixed +- **Sincronización Recíproca de Metadatos y Auto-Conexión Mercure (`PluginService`, `GroupsComponent`)**: + - Solucionado el fallo de actualización del tiempo restante en vivo: `meta.remaining_minutes` (snake_case fijado en la carga inicial HTTP) bloqueaba la lectura de las actualizaciones reactivas de Mercure emitidas en camelCase (`remainingMinutes`). + - `setPluginMetadata` normaliza y actualiza recíprocamente ambas claves (`remainingMinutes` y `remaining_minutes`) en cada evento recibido. + - Auto-conexión garantizada de Mercure en `PluginService`: si la URL de Mercure se resuelve de forma asíncrona tras la carga de la configuración, se conecta de manera transparente al solicitar estados o badges. + - Implementado sondeo de seguridad en segundo plano cada 30 segundos en `GroupsComponent` para mantener siempre sincronizados los minutos y badges de plugins ante micro-cortes o reconexiones de SSE. + ## [1.24.2] - 2026-10-30 ### Fixed diff --git a/ogWebconsole/package.json b/ogWebconsole/package.json index 33cf26f..9612d56 100644 --- a/ogWebconsole/package.json +++ b/ogWebconsole/package.json @@ -1,6 +1,6 @@ { "name": "og-webconsole", - "version": "1.24.2", + "version": "1.24.3", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/ogWebconsole/src/app/components/groups/groups.component.ts b/ogWebconsole/src/app/components/groups/groups.component.ts index 28981bd..53d0d09 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.ts +++ b/ogWebconsole/src/app/components/groups/groups.component.ts @@ -9,7 +9,7 @@ import { ToastrService } from 'ngx-toastr'; import { JoyrideService } from 'ngx-joyride'; import { FlatTreeControl } from '@angular/cdk/tree'; import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree'; -import { Subscription } from 'rxjs'; +import { Subscription, interval } from 'rxjs'; import { DataService } from './services/data.service'; import { UnidadOrganizativa, Client, TreeNode, FlatNode, Command } from './model/model'; import { ManageOrganizationalUnitComponent } from './shared/organizational-units/manage-organizational-unit/manage-organizational-unit.component'; @@ -274,9 +274,17 @@ export class GroupsComponent implements OnInit, OnDestroy { this.subscriptions.add( this.pluginService.statusUpdates$.subscribe(() => { + this.cd.markForCheck(); this.cd.detectChanges(); }) ); + + // Sincronización periódica de seguridad cada 30s para refrescar tiempo restante y estado de plugins + this.subscriptions.add( + interval(30000).subscribe(() => { + this.pluginService.loadActivePluginsStatus().subscribe(); + }) + ); } private updateClientStatus(clientUuid: string, status: string): void { diff --git a/ogWebconsole/src/app/services/plugin.service.ts b/ogWebconsole/src/app/services/plugin.service.ts index 99bf27e..dd2c98e 100644 --- a/ogWebconsole/src/app/services/plugin.service.ts +++ b/ogWebconsole/src/app/services/plugin.service.ts @@ -168,7 +168,17 @@ export class PluginService { public setPluginMetadata(pluginName: string, idOrUuid: string | number, metadata: any): void { const key = this.getStatusKey(pluginName, idOrUuid); const existing = this.clientPluginMetadataMap.get(key) || {}; - this.clientPluginMetadataMap.set(key, { ...existing, ...metadata }); + const updated = { ...existing, ...metadata }; + + // Sincronizar recíprocamente remainingMinutes y remaining_minutes para evitar discrepancias snake/camelCase + const remMins = metadata.remainingMinutes !== undefined ? metadata.remainingMinutes + : (metadata.remaining_minutes !== undefined ? metadata.remaining_minutes : undefined); + if (remMins !== undefined) { + updated.remaining_minutes = remMins; + updated.remainingMinutes = remMins; + } + + this.clientPluginMetadataMap.set(key, updated); } public getPluginMetadata(pluginName: string, idOrUuid: string | number): any { @@ -369,6 +379,7 @@ export class PluginService { } loadActivePluginsStatus(): Observable { + this.initMercureSubscription(); const apiUrl = this.configService.apiUrl; if (!apiUrl || this.activePlugins.length === 0) { return of(undefined); @@ -660,6 +671,9 @@ export class PluginService { } getClientBadges(client: any): PluginBadge[] { + if (!this.mercureEventSource) { + this.initMercureSubscription(); + } const badges: PluginBadge[] = []; if (!client || this.activePlugins.length === 0) return badges; @@ -718,7 +732,7 @@ export class PluginService { if (meta) { const dni = meta.dni || meta.user || meta.student; - const mins = meta.remaining_minutes !== undefined ? meta.remaining_minutes : meta.remainingMinutes; + const mins = meta.remainingMinutes !== undefined ? meta.remainingMinutes : meta.remaining_minutes; const infoParts: string[] = []; if (dni) { infoParts.push(`DNI: ${dni}`);