// static/js/csharp_launcher.js - Gestor para Launcher C# class CSharpLauncherManager { constructor() { this.currentProject = null; this.projects = []; this.executables = []; this.favorites = new Set(); this.runningProcesses = []; this.categories = [ 'Aplicaciones', 'Herramientas', 'Análisis', 'Desarrollo', 'APIs', 'Otros' ]; this.currentCategory = 'all'; this.initialized = false; this.processInterval = null; } async init() { console.log('Initializing C# Launcher Manager...'); // Limpiar estado previo si existe this.clearState(); await this.loadProjects(); await this.loadFavorites(); this.setupEventListeners(); this.renderInterface(); await this.refreshProcesses(); // Actualizar procesos cada 10 segundos if (!this.processInterval) { this.processInterval = setInterval(() => this.refreshProcesses(), 10000); } this.initialized = true; console.log('C# Launcher Manager initialized successfully'); } clearState() { console.log('Clearing C# launcher state...'); this.currentProject = null; this.projects = []; this.executables = []; this.favorites = new Set(); this.runningProcesses = []; // Limpiar intervalos previos if (this.processInterval) { clearInterval(this.processInterval); this.processInterval = null; } } // Método de utilidad para resetear completamente el launcher async reset() { console.log('Resetting C# Launcher...'); localStorage.removeItem('csharp_last_selected_project'); this.clearState(); await this.init(); } async loadProjects() { try { const response = await fetch('/api/csharp-projects'); if (response.ok) { this.projects = await response.json(); this.renderProjectSelector(); } else { console.error('Error loading C# projects:', await response.text()); } } catch (error) { console.error('Error loading C# projects:', error); } } async loadFavorites() { try { const response = await fetch('/api/csharp-favorites'); if (response.ok) { const data = await response.json(); this.favorites = new Set(data.favorites.map(fav => `${fav.project_id}_${fav.exe_name}`)); this.renderFavoritesPanel(); } else { console.error('Error loading C# favorites:', await response.text()); } } catch (error) { console.error('Error loading C# favorites:', error); } } setupEventListeners() { // Event listeners específicos del launcher C# const projectSelect = document.getElementById('csharp-project-select'); if (projectSelect) { projectSelect.addEventListener('change', (e) => this.onProjectChange(e)); } } renderInterface() { this.renderProjectSelector(); this.renderCategoryFilter(); this.renderFavoritesPanel(); } renderProjectSelector() { const select = document.getElementById('csharp-project-select'); if (!select) { console.warn('C# project select element not found'); return; } select.innerHTML = ''; this.projects.forEach(project => { const option = document.createElement('option'); option.value = project.id; option.textContent = project.name; option.setAttribute('data-description', project.description || ''); option.setAttribute('data-category', project.category || 'Otros'); select.appendChild(option); }); // Restaurar última selección con delay para asegurar que el DOM esté listo setTimeout(() => this.restoreLastSelectedProject(), 100); } restoreLastSelectedProject() { try { const lastSelectedProject = localStorage.getItem('csharp_last_selected_project'); console.log('Restoring last selected project:', lastSelectedProject); if (!lastSelectedProject) { console.log('No last selected project found'); return; } const project = this.projects.find(p => p.id === lastSelectedProject); if (!project) { console.log('Last selected project not found in current projects list, clearing localStorage'); localStorage.removeItem('csharp_last_selected_project'); return; } const select = document.getElementById('csharp-project-select'); if (!select) { console.warn('Project select element not found during restore'); return; } console.log('Restoring project:', project.name); select.value = lastSelectedProject; // Disparar evento change para cargar el proyecto const changeEvent = new Event('change', { bubbles: true }); select.dispatchEvent(changeEvent); } catch (error) { console.error('Error restoring last selected project:', error); // Limpiar localStorage corrupto localStorage.removeItem('csharp_last_selected_project'); } } async onProjectChange(e) { const projectId = e.target.value; console.log('Project change event:', projectId); if (!projectId) { console.log('No project selected, clearing state'); this.currentProject = null; this.hideCSharpProjectButtons(); this.clearExecutables(); // Limpiar persistencia localStorage.removeItem('csharp_last_selected_project'); return; } try { this.currentProject = this.projects.find(p => p.id === projectId); if (!this.currentProject) { console.error('Project not found:', projectId); return; } console.log('Loading project:', this.currentProject.name); this.showCSharpProjectButtons(); await this.loadProjectExecutables(projectId); // Guardar selección para persistencia localStorage.setItem('csharp_last_selected_project', projectId); console.log('Project loaded successfully'); } catch (error) { console.error('Error changing project:', error); this.showNotification('Error cargando el proyecto', 'error'); } } showCSharpProjectButtons() { const buttons = ['cursor-csharp-btn', 'vs2022-csharp-btn', 'folder-csharp-btn', 'copy-path-csharp-btn', 'manage-csharp-executables-btn']; buttons.forEach(id => { const btn = document.getElementById(id); if (btn) btn.style.display = 'block'; }); } hideCSharpProjectButtons() { const buttons = ['cursor-csharp-btn', 'vs2022-csharp-btn', 'folder-csharp-btn', 'copy-path-csharp-btn', 'manage-csharp-executables-btn']; buttons.forEach(id => { const btn = document.getElementById(id); if (btn) btn.style.display = 'none'; }); } async loadProjectExecutables(projectId) { try { const response = await fetch(`/api/csharp-executables/${projectId}`); if (response.ok) { this.executables = await response.json(); this.renderExecutables(); } else { console.error('Error loading executables:', await response.text()); this.executables = []; this.renderExecutables(); } } catch (error) { console.error('Error loading executables:', error); this.executables = []; this.renderExecutables(); } } renderExecutables() { const grid = document.getElementById('csharp-executables-grid'); if (!grid) return; // Filtrar por categoría si no es 'all' let filteredExecutables = this.executables; if (this.currentCategory !== 'all' && this.currentProject) { filteredExecutables = this.executables.filter(exe => this.currentProject.category === this.currentCategory ); } if (filteredExecutables.length === 0) { grid.innerHTML = `
🔍
No se encontraron ejecutables en este proyecto
Busque en: bin/Release y bin/Debug
`; return; } grid.innerHTML = filteredExecutables.map(exe => this.createExecutableCard(exe)).join(''); // Cargar argumentos para cada ejecutable después de renderizar filteredExecutables.forEach(exe => { this.loadExecutableArgumentsForCard(this.currentProject.id, exe.filename); }); } createExecutableCard(exe) { const favoriteKey = `${this.currentProject.id}_${exe.filename}`; const isFavorite = this.favorites.has(favoriteKey); const buildTypeBadge = exe.build_type === 'Release' ? 'Release' : 'Debug'; // Los argumentos se cargan después de renderizar return `

${exe.display_name}

${exe.short_description}

${buildTypeBadge} ${exe.filename}
`; } async executeExecutable(projectId, exeName, args = [], workingDir = null) { try { const response = await fetch('/api/execute-csharp-executable', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ project_id: projectId, exe_name: exeName, args: args, working_dir: workingDir }) }); const result = await response.json(); if (result.status === 'success') { // Actualizar procesos después de un breve delay setTimeout(() => this.refreshProcesses(), 1000); } return result; } catch (error) { console.error('Error executing executable:', error); return { status: 'error', message: error.message }; } } async toggleFavorite(projectId, exeName) { try { const response = await fetch('/api/csharp-favorites', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ project_id: projectId, exe_name: exeName }) }); if (response.ok) { const result = await response.json(); const favoriteKey = `${projectId}_${exeName}`; if (result.is_favorite) { this.favorites.add(favoriteKey); } else { this.favorites.delete(favoriteKey); } this.renderExecutables(); this.renderFavoritesPanel(); } } catch (error) { console.error('Error toggling favorite:', error); } } renderFavoritesPanel() { const panel = document.getElementById('csharp-favorites-list'); const counter = document.getElementById('csharp-favorites-count'); if (!panel || !counter) return; counter.textContent = `${this.favorites.size} favoritos`; if (this.favorites.size === 0) { panel.innerHTML = '
No hay favoritos guardados
'; return; } // Crear lista de favoritos (simplificada - solo mostrar nombres) const favoriteItems = Array.from(this.favorites).map(key => { const [projectId, exeName] = key.split('_', 2); const project = this.projects.find(p => p.id === projectId); const projectName = project ? project.name : 'Proyecto desconocido'; return `
${exeName} ${projectName}
`; }).join(''); panel.innerHTML = favoriteItems; } async executeFavorite(projectId, exeName) { // Cambiar al proyecto si no está seleccionado if (!this.currentProject || this.currentProject.id !== projectId) { const select = document.getElementById('csharp-project-select'); if (select) { select.value = projectId; await this.onProjectChange({ target: { value: projectId } }); } } // Ejecutar el ejecutable await this.executeExecutable(projectId, exeName); } renderCategoryFilter() { // Las categorías ya están en el HTML, solo necesitamos la funcionalidad console.log('Category filter rendered'); } filterByCategory(category) { this.currentCategory = category; // Actualizar botones activos document.querySelectorAll('.csharp-category-btn').forEach(btn => { btn.classList.remove('active'); if (btn.getAttribute('data-category') === category) { btn.classList.add('active'); } }); this.renderExecutables(); } async refreshProcesses() { try { const response = await fetch('/api/csharp-running-processes'); if (response.ok) { const data = await response.json(); this.runningProcesses = data.processes || []; this.renderRunningProcesses(); } } catch (error) { console.error('Error refreshing processes:', error); } } renderRunningProcesses() { const container = document.getElementById('csharp-running-processes'); if (!container) return; if (this.runningProcesses.length === 0) { container.innerHTML = '
No hay procesos C# en ejecución
'; return; } const processItems = this.runningProcesses.map(process => { const startTime = new Date(process.start_time).toLocaleTimeString(); return `
${process.display_name} PID: ${process.pid} | Iniciado: ${startTime}
`; }).join(''); container.innerHTML = processItems; } async terminateProcess(pid) { try { const response = await fetch(`/api/csharp-process-terminate/${pid}`, { method: 'POST' }); if (response.ok) { await this.refreshProcesses(); } } catch (error) { console.error('Error terminating process:', error); } } async loadExecutableArgumentsForCard(projectId, exeName) { try { const response = await fetch(`/api/csharp-executable-arguments/${projectId}/${exeName}`); if (response.ok) { const data = await response.json(); const argsList = data.arguments || []; this.populateArgumentsCombo(exeName, argsList); } } catch (error) { console.error('Error loading arguments for card:', error); } } populateArgumentsCombo(exeName, argsList) { const comboId = `args-combo-${exeName.replace('.exe', '').replace(/[^a-zA-Z0-9]/g, '_')}`; const combo = document.getElementById(comboId); if (!combo) return; // Limpiar opciones existentes excepto "Sin argumentos" combo.innerHTML = ''; // Agregar argumentos predefinidos argsList.forEach((arg, index) => { const option = document.createElement('option'); option.value = arg.arguments; option.textContent = arg.description; option.title = arg.arguments; // Tooltip con los argumentos combo.appendChild(option); }); } async executeWithSelectedArgs(projectId, exeName) { const comboId = `args-combo-${exeName.replace('.exe', '').replace(/[^a-zA-Z0-9]/g, '_')}`; const combo = document.getElementById(comboId); const selectedArgs = combo ? combo.value : ''; if (selectedArgs) { const argsArray = selectedArgs.split(' ').filter(arg => arg.length > 0); await this.executeExecutable(projectId, exeName, argsArray); } else { await this.executeExecutable(projectId, exeName); } } clearExecutables() { const grid = document.getElementById('csharp-executables-grid'); if (grid) { grid.innerHTML = '
Selecciona un proyecto para ver los ejecutables
'; } } // === GESTIÓN DE PROYECTOS === openProjectEditor() { // Cargar proyectos existentes y mostrar modal this.renderExistingProjects(); this.clearProjectForm(); const modal = document.getElementById('csharp-project-editor-modal'); if (modal) { modal.classList.remove('hidden'); } } closeProjectEditor() { const modal = document.getElementById('csharp-project-editor-modal'); if (modal) { modal.classList.add('hidden'); } } clearProjectForm() { const form = document.getElementById('csharp-project-form'); if (form) { form.reset(); document.getElementById('csharp-project-id').value = ''; } // Ocultar botón de eliminar cuando se crea nuevo proyecto const deleteBtn = document.getElementById('delete-csharp-project-btn'); if (deleteBtn) { deleteBtn.style.display = 'none'; } } populateProjectForm(project) { document.getElementById('csharp-project-id').value = project.id || ''; document.getElementById('csharp-project-name').value = project.name || ''; document.getElementById('csharp-project-description').value = project.description || ''; document.getElementById('csharp-project-directory').value = project.directory || ''; document.getElementById('csharp-project-category').value = project.category || 'Otros'; document.getElementById('csharp-project-version').value = project.version || '1.0'; document.getElementById('csharp-project-author').value = project.author || ''; document.getElementById('csharp-project-dotnet-version').value = project.dotnet_version || ''; // Tags (convertir array a string) const tagsInput = document.getElementById('csharp-project-tags'); if (tagsInput && project.tags) { tagsInput.value = Array.isArray(project.tags) ? project.tags.join(', ') : project.tags; } // Mostrar botón de eliminar cuando se edita un proyecto existente const deleteBtn = document.getElementById('delete-csharp-project-btn'); if (deleteBtn) { deleteBtn.style.display = 'block'; } } async saveProject() { const projectData = { name: document.getElementById('csharp-project-name').value.trim(), description: document.getElementById('csharp-project-description').value.trim(), directory: document.getElementById('csharp-project-directory').value.trim(), category: document.getElementById('csharp-project-category').value || 'Otros', version: document.getElementById('csharp-project-version').value.trim() || '1.0', author: document.getElementById('csharp-project-author').value.trim(), dotnet_version: document.getElementById('csharp-project-dotnet-version').value.trim(), tags: document.getElementById('csharp-project-tags').value.split(',').map(tag => tag.trim()).filter(tag => tag) }; // Validación básica if (!projectData.name) { this.showNotification('El nombre del proyecto es requerido', 'error'); document.getElementById('csharp-project-name').focus(); return; } if (!projectData.directory) { this.showNotification('El directorio del proyecto es requerido', 'error'); document.getElementById('csharp-project-directory').focus(); return; } try { const projectId = document.getElementById('csharp-project-id').value; const isEdit = projectId && projectId.trim() !== ''; let response; if (isEdit) { // Actualizar proyecto existente response = await fetch(`/api/csharp-projects/${projectId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(projectData) }); } else { // Crear nuevo proyecto response = await fetch('/api/csharp-projects', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(projectData) }); } const result = await response.json(); if (response.ok && result.status === 'success') { // Recargar proyectos y cerrar modal await this.loadProjects(); this.closeProjectEditor(); this.showNotification(`Proyecto ${isEdit ? 'actualizado' : 'creado'} exitosamente`, 'success'); } else { this.showNotification(`Error: ${result.message || 'Error desconocido'}`, 'error'); } } catch (error) { console.error('Error saving project:', error); this.showNotification('Error al comunicarse con el servidor', 'error'); } } editProject(projectId) { const project = this.projects.find(p => p.id === projectId); if (project) { this.populateProjectForm(project); // No necesitamos abrir el modal aquí, ya debería estar abierto } } async deleteProject() { const projectId = document.getElementById('csharp-project-id').value; if (!projectId) { this.showNotification('No hay proyecto seleccionado para eliminar', 'error'); return; } const project = this.projects.find(p => p.id === projectId); const projectName = project ? project.name : 'este proyecto'; if (!confirm(`¿Estás seguro de que quieres eliminar ${projectName}?`)) { return; } try { const response = await fetch(`/api/csharp-projects/${projectId}`, { method: 'DELETE' }); const result = await response.json(); if (response.ok && result.status === 'success') { // Recargar proyectos y limpiar formulario await this.loadProjects(); this.clearProjectForm(); this.showNotification('Proyecto eliminado exitosamente', 'success'); } else { this.showNotification(`Error: ${result.message || 'Error desconocido'}`, 'error'); } } catch (error) { console.error('Error deleting project:', error); this.showNotification('Error al comunicarse con el servidor', 'error'); } } renderExistingProjects() { const container = document.getElementById('csharp-existing-projects'); if (!container) return; if (this.projects.length === 0) { container.innerHTML = '
No hay proyectos C# configurados
'; return; } const projectItems = this.projects.map(project => { const categoryInfo = this.getCategoryInfo(project.category); return `
${categoryInfo.icon}

${project.name}

${project.category}

${project.description || 'Sin descripción'}

${project.directory}

v${project.version} ${project.dotnet_version ? `.NET ${project.dotnet_version}` : ''} ${project.author ? `por ${project.author}` : ''}
`; }).join(''); container.innerHTML = projectItems; } getCategoryInfo(category) { const categories = { 'Aplicaciones': { icon: '🖥️', color: '#3B82F6' }, 'Herramientas': { icon: '🔧', color: '#10B981' }, 'Análisis': { icon: '📊', color: '#8B5CF6' }, 'Desarrollo': { icon: '💻', color: '#F59E0B' }, 'APIs': { icon: '🌐', color: '#EF4444' }, 'Otros': { icon: '📁', color: '#6B7280' } }; return categories[category] || categories['Otros']; } showNotification(message, type = 'info') { // Usar la función showToast global si está disponible, sino crear una simple if (typeof showToast === 'function') { showToast(message, type); } else { // Fallback simple const bgColor = type === 'success' ? 'bg-green-500' : type === 'error' ? 'bg-red-500' : 'bg-blue-500'; const notification = document.createElement('div'); notification.className = `fixed top-4 right-4 ${bgColor} text-white px-4 py-2 rounded-lg shadow-lg z-50`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 3000); } } async browseProjectDirectory() { try { const currentPath = document.getElementById('csharp-project-directory').value; const response = await fetch('/api/browse-directories', { method: 'GET', headers: { 'Content-Type': 'application/json' } }); if (response.ok) { const result = await response.json(); if (result.status === 'success' && result.path) { document.getElementById('csharp-project-directory').value = result.path; } } else { // Fallback a prompt si falla el navegador const newPath = prompt('Ingresa el directorio del proyecto C#:', currentPath); if (newPath !== null) { document.getElementById('csharp-project-directory').value = newPath.trim(); } } } catch (error) { console.error('Error browsing directory:', error); // Fallback a prompt si hay error const currentPath = document.getElementById('csharp-project-directory').value; const newPath = prompt('Ingresa el directorio del proyecto C#:', currentPath); if (newPath !== null) { document.getElementById('csharp-project-directory').value = newPath.trim(); } } } } // Funciones globales para el HTML function loadCSharpExecutables() { const select = document.getElementById('csharp-project-select'); if (select && window.csharpLauncherManager) { window.csharpLauncherManager.onProjectChange({ target: select }); } } function filterCSharpByCategory(category) { if (window.csharpLauncherManager) { window.csharpLauncherManager.filterByCategory(category); } } function refreshCSharpProcesses() { if (window.csharpLauncherManager) { window.csharpLauncherManager.refreshProcesses(); } } function openCSharpProjectEditor() { if (window.csharpLauncherManager) { window.csharpLauncherManager.openProjectEditor(); } } async function openCSharpProjectInEditor(editor) { if (!window.csharpLauncherManager?.currentProject) { alert('Selecciona un proyecto primero'); return; } const projectId = window.csharpLauncherManager.currentProject.id; try { const response = await fetch(`/api/open-editor/${editor}/csharp/${projectId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const result = await response.json(); if (response.ok && result.status === 'success') { const editorName = editor === 'cursor' ? 'Cursor' : 'Visual Studio 2022'; if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification(`${editorName} abierto exitosamente`, 'success'); } else { alert(`${editorName} abierto exitosamente`); } } else { const errorMsg = `Error: ${result.message}`; if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification(errorMsg, 'error'); } else { alert(errorMsg); } } } catch (error) { console.error(`Error opening ${editor}:`, error); const errorMsg = 'Error al comunicarse con el servidor'; if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification(errorMsg, 'error'); } else { alert(errorMsg); } } } async function openCSharpProjectFolder() { if (!window.csharpLauncherManager?.currentProject) { alert('Selecciona un proyecto primero'); return; } const projectId = window.csharpLauncherManager.currentProject.id; try { const response = await fetch(`/api/open-group-folder/csharp/${projectId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const result = await response.json(); if (response.ok && result.status === 'success') { if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification('Explorador abierto exitosamente', 'success'); } else { alert('Explorador abierto exitosamente'); } } else { const errorMsg = `Error: ${result.message}`; if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification(errorMsg, 'error'); } else { alert(errorMsg); } } } catch (error) { console.error('Error opening folder:', error); const errorMsg = 'Error al comunicarse con el servidor'; if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification(errorMsg, 'error'); } else { alert(errorMsg); } } } async function copyCSharpProjectPath() { if (!window.csharpLauncherManager?.currentProject) { alert('Selecciona un proyecto primero'); return; } const projectPath = window.csharpLauncherManager.currentProject.directory; try { await navigator.clipboard.writeText(projectPath); if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification('Path copiado al portapapeles', 'success'); } else { alert('Path copiado al portapapeles'); } } catch (error) { console.error('Error copying path:', error); // Fallback para navegadores que no soportan clipboard API const textArea = document.createElement('textarea'); textArea.value = projectPath; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification('Path copiado al portapapeles', 'success'); } else { alert('Path copiado al portapapeles'); } } catch (fallbackError) { if (window.csharpLauncherManager && window.csharpLauncherManager.showNotification) { window.csharpLauncherManager.showNotification('Error al copiar path', 'error'); } else { alert('Error al copiar path'); } } document.body.removeChild(textArea); } } function openCSharpExecutableManager() { // TODO: Implementar gestor de ejecutables alert('Gestor de ejecutables C# - Por implementar'); } // === FUNCIONES GLOBALES PARA GESTIÓN DE PROYECTOS === function closeCSharpProjectEditor() { if (window.csharpLauncherManager) { window.csharpLauncherManager.closeProjectEditor(); } } function saveCSharpProject() { if (window.csharpLauncherManager) { window.csharpLauncherManager.saveProject(); } } function deleteCSharpProject() { if (window.csharpLauncherManager) { window.csharpLauncherManager.deleteProject(); } } function browseCSharpProjectDirectory() { if (window.csharpLauncherManager) { window.csharpLauncherManager.browseProjectDirectory(); } } function openCSharpExecutableManager() { if (!csharpLauncherManager.currentProject) { alert('Selecciona un proyecto primero'); return; } const modal = document.getElementById('csharp-executable-manager'); if (modal) { modal.style.display = 'block'; loadCSharpExecutableManager(); } } async function loadCSharpExecutableManager() { if (!csharpLauncherManager.currentProject) return; try { const response = await fetch(`/api/csharp-all-executables/${csharpLauncherManager.currentProject.id}`); if (response.ok) { const executables = await response.json(); renderCSharpExecutableManager(executables); } else { console.error('Error loading all executables:', await response.text()); } } catch (error) { console.error('Error loading all executables:', error); } } function renderCSharpExecutableManager(executables) { const container = document.getElementById('csharp-executable-list'); if (!container) return; if (executables.length === 0) { container.innerHTML = `
📝
No se encontraron ejecutables en este proyecto
`; return; } container.innerHTML = executables.map(exe => `

${exe.display_name}

${exe.build_type} ${exe.hidden ? 'Oculto' : 'Visible'}

${exe.short_description}

${exe.filename}

`).join(''); } async function editCSharpExecutableMetadata(projectId, exeName) { try { const response = await fetch(`/api/csharp-executable-metadata/${projectId}/${exeName}`); const metadata = response.ok ? await response.json() : {}; showCSharpExecutableMetadataEditor(projectId, exeName, metadata); } catch (error) { console.error('Error loading executable metadata:', error); } } function showCSharpExecutableMetadataEditor(projectId, exeName, metadata) { const modalHtml = `

Editar Ejecutable: ${exeName}

`; document.body.insertAdjacentHTML('beforeend', modalHtml); document.getElementById('csharp-metadata-form').onsubmit = async (e) => { e.preventDefault(); await saveCSharpExecutableMetadata(projectId, exeName); }; } async function saveCSharpExecutableMetadata(projectId, exeName) { const metadata = { display_name: document.getElementById('metadata-display-name').value, short_description: document.getElementById('metadata-short-description').value, long_description: document.getElementById('metadata-long-description').value, hidden: document.getElementById('metadata-hidden').checked }; try { const response = await fetch(`/api/csharp-executable-metadata/${projectId}/${exeName}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(metadata) }); const result = await response.json(); if (result.status === 'success') { csharpLauncherManager.showNotification(result.message, 'success'); closeCSharpMetadataEditor(); await loadCSharpExecutableManager(); await csharpLauncherManager.loadProjectExecutables(projectId); } else { csharpLauncherManager.showNotification(result.message, 'error'); } } catch (error) { csharpLauncherManager.showNotification('Error guardando metadatos', 'error'); console.error('Error saving metadata:', error); } } function closeCSharpMetadataEditor() { const modal = document.getElementById('csharp-metadata-modal'); if (modal) modal.remove(); } async function editCSharpExecutableArguments(projectId, exeName) { try { const response = await fetch(`/api/csharp-executable-arguments/${projectId}/${exeName}`); const data = response.ok ? await response.json() : { arguments: [] }; showCSharpArgumentsEditor(projectId, exeName, data.arguments); } catch (error) { console.error('Error loading executable arguments:', error); } } function showCSharpArgumentsEditor(projectId, exeName, argsList) { const modalHtml = `

Argumentos de: ${exeName}

`; document.body.insertAdjacentHTML('beforeend', modalHtml); renderCSharpArguments(argsList); } function renderCSharpArguments(argsList) { const container = document.getElementById('csharp-arguments-list'); if (!container) return; container.innerHTML = argsList.map((arg, index) => `
`).join(''); if (argsList.length === 0) { container.innerHTML = `
⚙️
No hay argumentos configurados
Usa el botón "Agregar Argumento" para crear opciones predefinidas
`; } } function addCSharpArgument() { const container = document.getElementById('csharp-arguments-list'); if (!container) return; const currentArguments = collectCSharpArguments(); currentArguments.push({ description: '', arguments: '' }); renderCSharpArguments(currentArguments); } function removeCSharpArgument(index) { const currentArguments = collectCSharpArguments(); currentArguments.splice(index, 1); renderCSharpArguments(currentArguments); } function collectCSharpArguments() { const argumentItems = document.querySelectorAll('.argument-item'); const argsList = []; argumentItems.forEach(item => { const description = item.querySelector('.arg-description').value.trim(); const argumentValue = item.querySelector('.arg-value').value.trim(); if (description && argumentValue) { argsList.push({ description, arguments: argumentValue }); } }); return argsList; } async function saveCSharpExecutableArguments(projectId, exeName) { const argsList = collectCSharpArguments(); try { const response = await fetch(`/api/csharp-executable-arguments/${projectId}/${exeName}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ arguments: argsList }) }); const result = await response.json(); if (result.status === 'success') { csharpLauncherManager.showNotification(result.message, 'success'); closeCSharpArgumentsEditor(); // Recargar la lista de ejecutables si está abierto el gestor if (document.getElementById('csharp-executable-manager').style.display !== 'none') { await loadCSharpExecutableManager(); } // Recargar argumentos en las cards actuales if (csharpLauncherManager.currentProject) { csharpLauncherManager.loadExecutableArgumentsForCard(projectId, exeName); } } else { csharpLauncherManager.showNotification(result.message, 'error'); } } catch (error) { csharpLauncherManager.showNotification('Error guardando argumentos', 'error'); console.error('Error saving arguments:', error); } } function closeCSharpArgumentsEditor() { const modal = document.getElementById('csharp-arguments-modal'); if (modal) modal.remove(); } async function showCSharpExecutableArgs(projectId, exeName, displayName) { try { // Cargar argumentos predefinidos const response = await fetch(`/api/csharp-executable-arguments/${projectId}/${exeName}`); const data = response.ok ? await response.json() : { arguments: [] }; const predefinedArgs = data.arguments || []; showCSharpExecutableArgsModal(projectId, exeName, displayName, predefinedArgs); } catch (error) { console.error('Error loading predefined arguments:', error); showCSharpExecutableArgsModal(projectId, exeName, displayName, []); } } function showCSharpExecutableArgsModal(projectId, exeName, displayName, predefinedArgs) { const predefinedSection = predefinedArgs.length > 0 ? `
${predefinedArgs.map((arg, index) => ` `).join('')}
` : ''; const modalHtml = `

Ejecutar: ${displayName}

${predefinedSection}
`; document.body.insertAdjacentHTML('beforeend', modalHtml); } function selectPredefinedCSharpArguments(args, description) { const input = document.getElementById('csharp-custom-args'); if (input) { input.value = args; } } async function executeCSharpWithArgs(projectId, exeName) { const argsInput = document.getElementById('csharp-custom-args'); const argsString = argsInput ? argsInput.value.trim() : ''; const args = argsString ? argsString.split(' ').filter(arg => arg.length > 0) : []; closeCSharpArgsModal(); await csharpLauncherManager.executeExecutable(projectId, exeName, args); } function closeCSharpArgsModal() { const modal = document.getElementById('csharp-args-modal'); if (modal) modal.remove(); } function closeCSharpExecutableManager() { const modal = document.getElementById('csharp-executable-manager'); if (modal) modal.style.display = 'none'; } function showCSharpExecutableArgs(projectId, exeName, displayName) { // TODO: Implementar modal de argumentos para C# const args = prompt(`Argumentos para ${displayName}:`, ''); if (args !== null) { const argArray = args.trim() ? args.split(' ') : []; window.csharpLauncherManager.executeExecutable(projectId, exeName, argArray); } } // Asegurar inicialización cuando el DOM esté listo (function () { console.log('C# Launcher script loaded, preparing initialization...'); function initializeCSharpLauncher() { try { console.log('Initializing CSharpLauncherManager...'); if (!window.csharpLauncherManager) { window.csharpLauncherManager = new CSharpLauncherManager(); console.log('CSharpLauncherManager created successfully'); } } catch (error) { console.error('Error creating CSharpLauncherManager:', error); } } // Inicializar inmediatamente si el DOM ya está listo if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initializeCSharpLauncher); } else { initializeCSharpLauncher(); } })(); // Función global para debug window.debugCSharpLauncher = function () { console.log('=== C# Launcher Debug Info ==='); console.log('Initialized:', window.csharpLauncherManager.initialized); console.log('Projects:', window.csharpLauncherManager.projects); console.log('Current Project:', window.csharpLauncherManager.currentProject); console.log('Executables:', window.csharpLauncherManager.executables); console.log('Favorites:', Array.from(window.csharpLauncherManager.favorites)); console.log('localStorage:', localStorage.getItem('csharp_last_selected_project')); // Verificar elementos DOM const select = document.getElementById('csharp-project-select'); console.log('Project Select Element:', select); if (select) { console.log('Select Options:', select.options.length); console.log('Select Value:', select.value); } console.log('=============================='); }; // Función global para resetear window.resetCSharpLauncher = function () { console.log('Resetting C# Launcher...'); return window.csharpLauncherManager.reset(); }; // === FUNCIONES DE RESPALDO PARA EVITAR ERRORES DE REFERENCIA === // Asegurar que las funciones globales estén definidas antes de que se necesiten document.addEventListener('DOMContentLoaded', function () { console.log('DOM loaded, ensuring C# launcher functions are available...'); // Solo redefinir si no existe para evitar conflictos if (typeof window.openCSharpProjectEditor === 'undefined') { window.openCSharpProjectEditor = function () { if (!window.csharpLauncherManager) { console.error('csharpLauncherManager not initialized'); alert('Error: El launcher C# no está inicializado. Refresca la página.'); return; } window.csharpLauncherManager.openProjectEditor(); }; } if (typeof window.loadCSharpExecutables === 'undefined') { window.loadCSharpExecutables = function () { if (!window.csharpLauncherManager) { console.error('csharpLauncherManager not initialized'); return; } const select = document.getElementById('csharp-project-select'); if (select && window.csharpLauncherManager) { window.csharpLauncherManager.onProjectChange({ target: select }); } }; } if (typeof window.filterCSharpByCategory === 'undefined') { window.filterCSharpByCategory = function (category) { if (!window.csharpLauncherManager) { console.error('csharpLauncherManager not initialized'); return; } window.csharpLauncherManager.filterByCategory(category); }; } if (typeof window.refreshCSharpProcesses === 'undefined') { window.refreshCSharpProcesses = function () { if (!window.csharpLauncherManager) { console.error('csharpLauncherManager not initialized'); return; } window.csharpLauncherManager.refreshProcesses(); }; } if (typeof window.openCSharpExecutableManager === 'undefined') { window.openCSharpExecutableManager = function () { if (!window.csharpLauncherManager) { console.error('csharpLauncherManager not initialized'); alert('Error: El launcher C# no está inicializado. Refresca la página.'); return; } if (!window.csharpLauncherManager.currentProject) { alert('Por favor selecciona un proyecto primero'); return; } // Usar la función ya implementada loadCSharpExecutableManager(); }; } console.log('C# launcher backup functions initialized'); });