diff --git a/CHANGELOG.md b/CHANGELOG.md index e68753d..b2c2777 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [1.25.0] - 2026-11-01 + +### Added +- **Restricción Declarativa de Comandos de Plugins según Estado (`PluginService`, `ExecuteCommandComponent`)**: + - Incorporadas las propiedades opcionales `requireStatus` y `excludeStatus` en la interfaz `PluginCommand`, permitiendo a los plugins condicionar la disponibilidad de sus acciones en función del estado actual de los clientes. + - Implementado filtrado reactivo en `isCommandSupportedForClients`: los comandos solo se habilitan si el estado del equipo coincide con los estados requeridos (`requireStatus`) y no figura entre los estados excluidos (`excludeStatus`). + - Si un puesto de acceso libre (Aquarium) se encuentra desactivado (`DISABLED`), las opciones de reserva, liberación y renovación quedan deshabilitadas, permitiendo únicamente la acción de activación. + - Adaptación dinámica de etiqueta en comandos de conmutación de estado (`ogaquarium-toggle-status`): muestra "Activar puesto" o "Desactivar puesto" según el estado actual cuando se selecciona un único equipo. + - Suscripción reactiva a `statusUpdates$` en `ExecuteCommandComponent` para recalcular al instante la disponibilidad de acciones al recibir eventos Mercure en tiempo real. + ## [1.24.7] - 2026-10-31 ### Refactored diff --git a/ogWebconsole/package.json b/ogWebconsole/package.json index 0d9f381..1d84606 100644 --- a/ogWebconsole/package.json +++ b/ogWebconsole/package.json @@ -1,6 +1,6 @@ { "name": "og-webconsole", - "version": "1.24.7", + "version": "1.25.0", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts b/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts index 57169bf..cc602b1 100644 --- a/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts +++ b/ogWebconsole/src/app/components/commands/main-commands/execute-command/execute-command.component.ts @@ -79,6 +79,9 @@ export class ExecuteCommandComponent implements OnInit { this.pluginGroups = this.pluginService.getPluginGroups(); this.updateCommandStates(); }); + this.pluginService.statusUpdates$.subscribe(() => { + this.updateCommandStates(); + }); this.updateCommandStates(); } @@ -172,7 +175,24 @@ export class ExecuteCommandComponent implements OnInit { if (this.pluginGroups && this.pluginGroups.length > 0) { for (const group of this.pluginGroups) { for (const cmd of group.commands) { - cmd.disabled = !hasClients || !this.pluginService.isCommandSupportedForClients(cmd, this.clientData); + cmd.disabled = !hasClients || !this.pluginService.isCommandSupportedForClients(cmd, this.clientData, group.plugin.name); + + // Adaptar dinámicamente la etiqueta de activar/desactivar en ogaquarium si hay un solo cliente seleccionado + if (cmd.slug === 'ogaquarium-toggle-status' && this.clientData.length === 1) { + const client = this.clientData[0]; + const idKey = client.id ? String(client.id) : null; + const uuidKey = client.uuid || client.name; + const currentStatus = (idKey ? this.pluginService.getPluginStatus(group.plugin.name, idKey) : null) + || (uuidKey ? this.pluginService.getPluginStatus(group.plugin.name, uuidKey) : null) + || 'DISABLED'; + + if (currentStatus === 'DISABLED') { + cmd.label = this.translate.instant('ogaquarium.commands.activate') || 'Activar puesto'; + } else { + cmd.label = this.translate.instant('ogaquarium.commands.deactivate') || 'Desactivar puesto'; + } + cmd.labelKey = undefined; + } } } } diff --git a/ogWebconsole/src/app/services/plugin.service.ts b/ogWebconsole/src/app/services/plugin.service.ts index 9ab8c1c..5479a05 100644 --- a/ogWebconsole/src/app/services/plugin.service.ts +++ b/ogWebconsole/src/app/services/plugin.service.ts @@ -29,6 +29,8 @@ export interface PluginCommand { confirm?: string; confirmKey?: string; roles?: string[]; // Roles autorizados por defecto (ej. ['ROLE_SUPER_ADMIN', 'ROLE_ORGANIZATIONAL_UNIT_ADMIN']) + requireStatus?: string[]; // Estados requeridos del plugin para habilitar el comando + excludeStatus?: string[]; // Estados del plugin que deshabilitan el comando } export interface RoleDefinition { @@ -648,27 +650,57 @@ export class PluginService { return this.getCommands().find(c => c.slug === slug); } - isCommandSupportedForClients(command: PluginCommand, clients: any[]): boolean { - if (!command.os || command.os.length === 0) { - return true; - } + isCommandSupportedForClients(command: PluginCommand, clients: any[], pluginName?: string): boolean { if (!clients || clients.length === 0) { return true; } - const requiredOsList = command.os.map(os => os.toLowerCase()); + if (command.os && command.os.length > 0) { + const requiredOsList = command.os.map(os => os.toLowerCase()); + const osSupported = clients.every(client => { + const statusStr = (client.status || '').toLowerCase(); + const matchesStatus = requiredOsList.some(req => statusStr.includes(req)); - return clients.every(client => { - const statusStr = (client.status || '').toLowerCase(); - const matchesStatus = requiredOsList.some(req => statusStr.includes(req)); + const hasMatchingPartition = (client.partitions || []).some((partition: any) => { + const osName = (partition.operativeSystem?.name || partition.operativeSystem || '').toLowerCase(); + return requiredOsList.some(req => osName.includes(req)); + }); - const hasMatchingPartition = (client.partitions || []).some((partition: any) => { - const osName = (partition.operativeSystem?.name || partition.operativeSystem || '').toLowerCase(); - return requiredOsList.some(req => osName.includes(req)); + return matchesStatus || hasMatchingPartition; }); - return matchesStatus || hasMatchingPartition; - }); + if (!osSupported) { + return false; + } + } + + if (pluginName && (command.requireStatus || command.excludeStatus)) { + return clients.every(client => { + const idKey = client.id ? String(client.id) : null; + const uuidKey = client.uuid || client.name; + const currentStatus = (idKey ? this.getPluginStatus(pluginName, idKey) : null) + || (uuidKey ? this.getPluginStatus(pluginName, uuidKey) : null) + || 'DISABLED'; + + if (command.excludeStatus && command.excludeStatus.length > 0) { + const excludedUpper = command.excludeStatus.map(s => s.toUpperCase()); + if (excludedUpper.includes(currentStatus.toUpperCase())) { + return false; + } + } + + if (command.requireStatus && command.requireStatus.length > 0) { + const requiredUpper = command.requireStatus.map(s => s.toUpperCase()); + if (!requiredUpper.includes(currentStatus.toUpperCase())) { + return false; + } + } + + return true; + }); + } + + return true; } getClientBadges(client: any): PluginBadge[] {