From 2d9c66919a5a5be90ee04a562c6fbdcdd0da4d50 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Fri, 5 Sep 2025 12:12:11 +0200 Subject: [PATCH] refs #2756. Fixed bug with stored comands --- .../run-script-assistant.component.css | 270 ++++++++++++++++++ .../run-script-assistant.component.html | 176 ++++++++++-- .../run-script-assistant.component.ts | 24 +- 3 files changed, 439 insertions(+), 31 deletions(-) diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.css b/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.css index 615b9b9..9227a68 100644 --- a/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.css +++ b/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.css @@ -533,4 +533,274 @@ mat-spinner { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} + +.script-input-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + padding: 16px; + background: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.script-input-header h4 { + margin: 0; + display: flex; + align-items: center; + gap: 8px; + color: #2c3e50; + font-weight: 600; +} + +.script-stats { + display: flex; + gap: 16px; + align-items: center; +} + +.stat-item { + display: flex; + align-items: center; + gap: 4px; + font-size: 12px; + color: #6c757d; + background: white; + padding: 4px 8px; + border-radius: 4px; + border: 1px solid #e9ecef; +} + +.stat-item.valid { + color: #28a745; + border-color: #28a745; + background: #f8fff9; +} + +.stat-item.invalid { + color: #dc3545; + border-color: #dc3545; + background: #fff8f8; +} + +.stat-item mat-icon { + font-size: 14px; + width: 14px; + height: 14px; +} + +.script-textarea { + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 14px; + line-height: 1.5; + background: #f8f9fa; +} + +.detected-params { + background: #fff3cd; + border: 1px solid #ffeaa7; + border-radius: 8px; + padding: 16px; + margin: 16px 0; +} + +.detected-params h4 { + margin: 0 0 12px 0; + display: flex; + align-items: center; + gap: 8px; + color: #856404; + font-weight: 600; +} + +.params-grid .mat-mdc-chip-listbox { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.param-chip { + background: #fff !important; + border: 1px solid #ffeaa7 !important; + color: #856404 !important; +} + +.action-buttons { + display: flex; + justify-content: flex-end; + gap: 12px; + margin-top: 16px; +} + +.action-buttons button { + display: flex; + align-items: center; + gap: 8px; +} + +.script-selector-container { + margin-bottom: 20px; +} + +.script-option { + display: flex; + flex-direction: column; + gap: 2px; +} + +.script-name { + font-weight: 500; + color: #2c3e50; +} + +.script-description { + font-size: 12px; + color: #6c757d; + opacity: 0.8; +} + +/* Tarjetas de vista previa */ +.script-preview-container { + margin-top: 20px; +} + +.script-card, .params-card { + margin-bottom: 16px; + border: 1px solid #e3f2fd !important; + border-radius: 12px !important; +} + +.script-card .mat-mdc-card-header, +.params-card .mat-mdc-card-header { + background: #f8f9fa; + border-radius: 12px 12px 0 0; +} + +.script-card .mat-mdc-card-title, +.params-card .mat-mdc-card-title { + display: flex; + align-items: center; + gap: 8px; + color: #2c3e50; + font-weight: 600; +} + +.script-card .mat-mdc-card-subtitle, +.params-card .mat-mdc-card-subtitle { + color: #6c757d; + margin-top: 4px; +} + +.script-content-wrapper { + background: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; + max-height: 300px; + overflow-y: auto; +} + +.script-preview { + background-color: #ffffff; + border: 1px solid #e9ecef; + padding: 16px; + border-radius: 8px; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 13px; + line-height: 1.6; + white-space: pre-wrap; + min-height: 60px; + max-height: 280px; + overflow-y: auto; +} + +.script-params-section { + margin-top: 16px; +} + +.params-count { + background: #667eea !important; + color: white !important; + font-size: 11px; + height: 20px; + min-height: 20px; + padding: 0 8px; +} + +.params-form { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 16px; +} + +.param-field { + position: relative; +} + +/* Estados vacíos */ +.empty-state { + display: flex; + justify-content: center; + align-items: center; + min-height: 200px; + background: #f8f9fa; + border: 2px dashed #e9ecef; + border-radius: 12px; + margin: 20px 0; +} + +.empty-state-content { + text-align: center; + color: #6c757d; +} + +.empty-state-content mat-icon { + font-size: 48px; + width: 48px; + height: 48px; + color: #dee2e6; + margin-bottom: 16px; +} + +.empty-state-content h3 { + margin: 0 0 8px 0; + color: #495057; + font-weight: 500; +} + +.empty-state-content p { + margin: 0; + font-size: 14px; + max-width: 300px; +} + +/* Mejoras en chips de acción */ +::ng-deep .action-chip mat-icon { + font-size: 18px !important; + width: 18px !important; + height: 18px !important; + margin-right: 4px !important; +} + +/* Responsive design */ +@media (max-width: 768px) { + .script-input-header { + flex-direction: column; + align-items: flex-start; + gap: 12px; + } + + .script-stats { + flex-wrap: wrap; + gap: 8px; + } + + .params-form { + grid-template-columns: 1fr; + } + + .action-buttons { + justify-content: center; + } } \ No newline at end of file diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.html b/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.html index c9bef47..7e772c9 100644 --- a/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.html +++ b/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.html @@ -86,50 +86,168 @@
+ add_circle Nuevo Script + folder Script Guardado
- +
- - Ingrese el script - - - -
- -
- - Seleccione script a ejecutar - - {{ script.name }} - - -
- -
-
-

Script:

-
+
+

+ edit_note + Editor de Script +

+
+ + format_list_numbered + {{ getLineCount(newScript) }} líneas + + + text_fields + {{ newScript.length }} caracteres + + + {{ isScriptValid(newScript) ? 'check_circle' : 'error' }} + {{ isScriptValid(newScript) ? 'Válido' : 'Requiere contenido' }} + +
-
-

Ingrese los parámetros:

-
- - {{ paramName }} - - + + Ingrese el script + + Escriba comandos de shell/bash. Use @parametro para variables dinámicas. + + + +
+

+ tune + Parámetros detectados +

+
+ + + label + @{{ param }} + + +
+
+ +
+ +
+
+ + +
+
+ + Seleccione script a ejecutar + + +
+ {{ script.name }} + {{ script.description }} +
+
+
+ No hay scripts guardados disponibles + {{ scripts.length }} script(s) disponible(s) +
+
+ + +
+ + + + preview + Vista previa del script + + {{ selectedScript.name }} + + + +
+
+
+
+
+ + +
+ + + + settings + Parámetros del script + {{ parameterNames.length }} + + Configure los valores para los parámetros requeridos + + + +
+
+ + {{ paramName }} + + label + Parámetro: @{{ paramName }} + Este parámetro es requerido + +
+
+
+
-
+ +
+
+ folder_open +

Selecciona un script

+

Elige un script guardado de la lista para ver su contenido y configurar parámetros.

+
+
+ + +
+
+ edit_note +

Escribe tu script

+

Crea un nuevo script escribiendo comandos de shell/bash en el editor de texto.

+
+
+
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.ts b/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.ts index 90a2c8e..32f2c91 100644 --- a/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.ts +++ b/ogWebconsole/src/app/components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component.ts @@ -35,6 +35,7 @@ export class RunScriptAssistantComponent implements OnInit{ selection = new SelectionModel(true, []); parameterNames: string[] = Object.keys(this.parameters); runScriptContext: any = null; + newScriptParameters: string[] = []; constructor( private http: HttpClient, @@ -168,6 +169,24 @@ export class RunScriptAssistantComponent implements OnInit{ this.scriptContent = updatedScript; } + getLineCount(text: string): number { + if (!text) return 0; + return text.split('\n').length; + } + + isScriptValid(script: string): boolean { + return Boolean(script && script.trim().length > 0); + } + + onNewScriptChange(): void { + const matches = this.newScript.match(/@(\w+)/g) || []; + this.newScriptParameters = Array.from(new Set(matches.map(m => m.slice(1)))); + } + + trackByParam(index: number, paramName: string): string { + return paramName; + } + save(): void { const dialogRef = this.dialog.open(QueueConfirmationModalComponent, { width: '400px', @@ -228,11 +247,12 @@ export class RunScriptAssistantComponent implements OnInit{ }); dialogRef.afterClosed().subscribe(result => { + console.log(result); if (result) { this.http.post(`${this.baseUrl}/command-task-scripts`, { - commandTask: result.taskId['@id'], + commandTask: result['@id'], content: this.commandType === 'existing' ? this.scriptContent : this.newScript, - order: result.executionOrder, + order: result['executionOrder'] || 1, type: 'run-script', }).subscribe({ next: () => {