182 lines
6.0 KiB
TypeScript
182 lines
6.0 KiB
TypeScript
import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChanges, inject } from '@angular/core';
|
|
import { HttpClient } from '@angular/common/http';
|
|
import { PluginManifest, PluginService, SchemaField } from '@services/plugin.service';
|
|
import { ConfigService } from '@services/config.service';
|
|
import { ToastrService } from 'ngx-toastr';
|
|
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
|
import { Subscription } from 'rxjs';
|
|
|
|
@Component({
|
|
selector: 'app-plugin-settings',
|
|
templateUrl: './plugin-settings.component.html',
|
|
styleUrls: ['./plugin-settings.component.css']
|
|
})
|
|
export class PluginSettingsComponent implements OnInit, OnChanges, OnDestroy {
|
|
@Input() pluginName: string = '';
|
|
|
|
plugin?: PluginManifest;
|
|
schema: SchemaField[] = [];
|
|
configData: Record<string, any> = {};
|
|
editingScripts: Record<string, boolean> = {};
|
|
|
|
private pluginSub?: Subscription;
|
|
private sanitizer = inject(DomSanitizer);
|
|
private http = inject(HttpClient);
|
|
private configService = inject(ConfigService);
|
|
|
|
constructor(
|
|
private pluginService: PluginService,
|
|
private toast: ToastrService
|
|
) {}
|
|
|
|
ngOnInit(): void {
|
|
this.pluginSub = this.pluginService.plugins$.subscribe(() => {
|
|
this.loadPluginData();
|
|
});
|
|
this.loadPluginData();
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
this.pluginSub?.unsubscribe();
|
|
}
|
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
if (changes['pluginName']) {
|
|
this.loadPluginData();
|
|
}
|
|
}
|
|
|
|
private loadPluginData(): void {
|
|
if (!this.pluginName) return;
|
|
this.plugin = this.pluginService.getPlugin(this.pluginName);
|
|
if (this.plugin) {
|
|
this.schema = this.plugin.schema;
|
|
this.configData = this.pluginService.getPluginConfig(this.pluginName);
|
|
}
|
|
}
|
|
|
|
toggleEnabled(checked: boolean): void {
|
|
if (!this.pluginName) return;
|
|
this.pluginService.togglePlugin(this.pluginName, checked).subscribe({
|
|
next: () => {
|
|
const statusText = checked ? 'activado' : 'desactivado';
|
|
this.toast.success(`Plugin ${statusText} correctamente`, this.plugin?.title || 'Plugin');
|
|
},
|
|
error: () => {
|
|
this.toast.error('Error al cambiar el estado del plugin', this.plugin?.title || 'Plugin');
|
|
this.loadPluginData();
|
|
}
|
|
});
|
|
}
|
|
|
|
runFieldAction(field: SchemaField): void {
|
|
if (!field.action || !field.action.endpoint) return;
|
|
|
|
const apiUrl = this.configService.apiUrl || '';
|
|
const cleanEndpoint = field.action.endpoint.replace(/^\/api/, '');
|
|
const url = `${apiUrl}${cleanEndpoint}`;
|
|
|
|
this.http.post<any>(url, { config: this.configData }).subscribe({
|
|
next: (response) => {
|
|
if (response && response.data) {
|
|
this.configData = { ...this.configData, ...response.data };
|
|
}
|
|
const message = response?.message || `${field.action?.label} completado correctamente`;
|
|
this.toast.info(message, this.plugin?.title || 'Plugin');
|
|
},
|
|
error: (err) => {
|
|
const errorMsg = err?.error?.message || 'Error al ejecutar la acción del plugin';
|
|
this.toast.error(errorMsg, field.action?.label || 'Plugin');
|
|
}
|
|
});
|
|
}
|
|
|
|
isEditingScript(key: string): boolean {
|
|
return !!this.editingScripts[key];
|
|
}
|
|
|
|
toggleScriptEdit(key: string): void {
|
|
this.editingScripts[key] = !this.editingScripts[key];
|
|
}
|
|
|
|
copyToClipboard(text: string): void {
|
|
if (!text) return;
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
this.toast.success('Script copiado al portapapeles', 'Portapapeles');
|
|
}).catch(() => {
|
|
this.toast.error('No se pudo copiar el script al portapapeles', 'Error');
|
|
});
|
|
}
|
|
|
|
getScriptLines(script: string): SafeHtml[] {
|
|
if (!script) return [];
|
|
const lines = script.split('\n');
|
|
return lines.map(line => this.highlightLine(line));
|
|
}
|
|
|
|
private escapeHtml(str: string): string {
|
|
return str
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>');
|
|
}
|
|
|
|
private highlightLine(rawLine: string): SafeHtml {
|
|
const trimmed = rawLine.trim();
|
|
|
|
if (trimmed.length === 0) {
|
|
return this.sanitizer.bypassSecurityTrustHtml(' ');
|
|
}
|
|
|
|
// Comentario completo
|
|
if (trimmed.startsWith('#')) {
|
|
const escaped = this.escapeHtml(rawLine);
|
|
return this.sanitizer.bypassSecurityTrustHtml(`<span class="syntax-comment">${escaped}</span>`);
|
|
}
|
|
|
|
let escaped = this.escapeHtml(rawLine);
|
|
|
|
// 1. Cadenas entre comillas dobles o simples
|
|
const strings: string[] = [];
|
|
escaped = escaped.replace(/(["'])(.*?)\1/g, (match) => {
|
|
strings.push(match);
|
|
return `___STR_${strings.length - 1}___`;
|
|
});
|
|
|
|
// 2. Parámetros / flags (/r, /t, -c, etc.)
|
|
escaped = escaped.replace(/(\s)([\/-][a-zA-Z0-9?]+)/g, '$1<span class="syntax-flag">$2</span>');
|
|
|
|
// 3. Comandos ejecutables
|
|
escaped = escaped.replace(/\b(uwfmgr\.exe|shutdown|powershell\.exe|cmd\.exe)\b/gi, '<span class="syntax-cmd">$1</span>');
|
|
|
|
// 4. Subcomandos y palabras clave
|
|
escaped = escaped.replace(/\b(overlay|filter|volume|file|enable|disable|protect|set-type|set-size|add-exclusion)\b/gi, '<span class="syntax-keyword">$1</span>');
|
|
|
|
// 5. Valores y tipos
|
|
escaped = escaped.replace(/\b(RAM|DISK|true|false)\b/gi, '<span class="syntax-val">$1</span>');
|
|
|
|
// 6. Números
|
|
escaped = escaped.replace(/\b(\d+)\b/g, '<span class="syntax-num">$1</span>');
|
|
|
|
// Restaurar cadenas
|
|
escaped = escaped.replace(/___STR_(\d+)___/g, (_, index) => {
|
|
const original = strings[Number(index)];
|
|
return `<span class="syntax-string">${original}</span>`;
|
|
});
|
|
|
|
return this.sanitizer.bypassSecurityTrustHtml(escaped);
|
|
}
|
|
|
|
save(): void {
|
|
if (!this.pluginName) return;
|
|
this.pluginService.savePluginConfig(this.pluginName, this.configData);
|
|
this.toast.success('Configuración guardada correctamente', this.plugin?.title || 'Plugin');
|
|
}
|
|
|
|
reset(): void {
|
|
if (!this.pluginName) return;
|
|
this.configData = this.pluginService.resetPluginConfig(this.pluginName);
|
|
this.toast.info('Configuración restaurada a valores por defecto', this.plugin?.title || 'Plugin');
|
|
}
|
|
}
|