feat: declarative plugin command status filtering and dynamic action labels v1.25.0
parent
dc4186ff4d
commit
bfc7e07e2a
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -1,5 +1,15 @@
|
||||||
# Changelog
|
# 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
|
## [1.24.7] - 2026-10-31
|
||||||
|
|
||||||
### Refactored
|
### Refactored
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "og-webconsole",
|
"name": "og-webconsole",
|
||||||
"version": "1.24.7",
|
"version": "1.25.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,9 @@ export class ExecuteCommandComponent implements OnInit {
|
||||||
this.pluginGroups = this.pluginService.getPluginGroups();
|
this.pluginGroups = this.pluginService.getPluginGroups();
|
||||||
this.updateCommandStates();
|
this.updateCommandStates();
|
||||||
});
|
});
|
||||||
|
this.pluginService.statusUpdates$.subscribe(() => {
|
||||||
|
this.updateCommandStates();
|
||||||
|
});
|
||||||
|
|
||||||
this.updateCommandStates();
|
this.updateCommandStates();
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +175,24 @@ export class ExecuteCommandComponent implements OnInit {
|
||||||
if (this.pluginGroups && this.pluginGroups.length > 0) {
|
if (this.pluginGroups && this.pluginGroups.length > 0) {
|
||||||
for (const group of this.pluginGroups) {
|
for (const group of this.pluginGroups) {
|
||||||
for (const cmd of group.commands) {
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ export interface PluginCommand {
|
||||||
confirm?: string;
|
confirm?: string;
|
||||||
confirmKey?: string;
|
confirmKey?: string;
|
||||||
roles?: string[]; // Roles autorizados por defecto (ej. ['ROLE_SUPER_ADMIN', 'ROLE_ORGANIZATIONAL_UNIT_ADMIN'])
|
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 {
|
export interface RoleDefinition {
|
||||||
|
|
@ -648,27 +650,57 @@ export class PluginService {
|
||||||
return this.getCommands().find(c => c.slug === slug);
|
return this.getCommands().find(c => c.slug === slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCommandSupportedForClients(command: PluginCommand, clients: any[]): boolean {
|
isCommandSupportedForClients(command: PluginCommand, clients: any[], pluginName?: string): boolean {
|
||||||
if (!command.os || command.os.length === 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!clients || clients.length === 0) {
|
if (!clients || clients.length === 0) {
|
||||||
return true;
|
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 hasMatchingPartition = (client.partitions || []).some((partition: any) => {
|
||||||
const statusStr = (client.status || '').toLowerCase();
|
const osName = (partition.operativeSystem?.name || partition.operativeSystem || '').toLowerCase();
|
||||||
const matchesStatus = requiredOsList.some(req => statusStr.includes(req));
|
return requiredOsList.some(req => osName.includes(req));
|
||||||
|
});
|
||||||
|
|
||||||
const hasMatchingPartition = (client.partitions || []).some((partition: any) => {
|
return matchesStatus || hasMatchingPartition;
|
||||||
const osName = (partition.operativeSystem?.name || partition.operativeSystem || '').toLowerCase();
|
|
||||||
return requiredOsList.some(req => osName.includes(req));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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[] {
|
getClientBadges(client: any): PluginBadge[] {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue