ParamManagerScripts/static/js/csharp_launcher.js

467 lines
17 KiB
JavaScript

// 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';
}
async init() {
console.log('Initializing C# Launcher Manager...');
await this.loadProjects();
await this.loadFavorites();
this.setupEventListeners();
this.renderInterface();
await this.refreshProcesses();
// Actualizar procesos cada 10 segundos
setInterval(() => this.refreshProcesses(), 10000);
}
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) return;
select.innerHTML = '<option value="">-- Seleccionar Proyecto --</option>';
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);
});
}
async onProjectChange(e) {
const projectId = e.target.value;
if (!projectId) {
this.currentProject = null;
this.hideCSharpProjectButtons();
this.clearExecutables();
return;
}
try {
this.currentProject = this.projects.find(p => p.id === projectId);
this.showCSharpProjectButtons();
await this.loadProjectExecutables(projectId);
} catch (error) {
console.error('Error changing project:', error);
}
}
showCSharpProjectButtons() {
const buttons = ['cursor-csharp-btn', 'vs2022-csharp-btn', 'folder-csharp-btn', 'copy-path-csharp-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'];
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 = `
<div class="col-span-full text-center py-8 text-gray-500">
<div class="text-4xl mb-2">🔍</div>
<div>No se encontraron ejecutables en este proyecto</div>
<div class="text-sm mt-1">Busque en: bin/Release y bin/Debug</div>
</div>
`;
return;
}
grid.innerHTML = filteredExecutables.map(exe => this.createExecutableCard(exe)).join('');
}
createExecutableCard(exe) {
const favoriteKey = `${this.currentProject.id}_${exe.filename}`;
const isFavorite = this.favorites.has(favoriteKey);
const buildTypeBadge = exe.build_type === 'Release' ?
'<span class="text-xs bg-green-100 text-green-800 px-2 py-1 rounded">Release</span>' :
'<span class="text-xs bg-yellow-100 text-yellow-800 px-2 py-1 rounded">Debug</span>';
return `
<div class="executable-card bg-white border rounded-lg p-4 hover:shadow-md transition-shadow">
<div class="flex justify-between items-start mb-2">
<h4 class="font-medium text-sm">${exe.display_name}</h4>
<button class="favorite-star text-gray-300 hover:text-yellow-500 ${isFavorite ? 'text-yellow-500' : ''}"
onclick="csharpLauncherManager.toggleFavorite('${this.currentProject.id}', '${exe.filename}')">⭐</button>
</div>
<p class="text-xs text-gray-600 mb-2">${exe.short_description}</p>
<div class="flex justify-between items-center mb-3">
${buildTypeBadge}
<span class="text-xs text-gray-500">${exe.filename}</span>
</div>
<div class="flex justify-between items-center">
<div class="space-x-1">
<button class="text-blue-500 hover:underline text-xs"
onclick="showCSharpExecutableArgs('${this.currentProject.id}', '${exe.filename}', '${exe.display_name}')">
Con Argumentos
</button>
</div>
<button class="bg-blue-500 text-white px-3 py-1 rounded text-xs hover:bg-blue-600"
onclick="csharpLauncherManager.executeExecutable('${this.currentProject.id}', '${exe.filename}')">
Ejecutar
</button>
</div>
</div>
`;
}
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 = '<div class="text-center text-gray-500 py-2">No hay favoritos guardados</div>';
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 `
<div class="flex justify-between items-center bg-white p-2 rounded border">
<div>
<span class="font-medium text-sm">${exeName}</span>
<span class="text-xs text-gray-500 ml-2">${projectName}</span>
</div>
<button class="text-blue-500 hover:text-blue-700 text-xs"
onclick="csharpLauncherManager.executeFavorite('${projectId}', '${exeName}')">
Ejecutar
</button>
</div>
`;
}).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 = '<div class="text-center text-gray-500 py-2">No hay procesos C# en ejecución</div>';
return;
}
const processItems = this.runningProcesses.map(process => {
const startTime = new Date(process.start_time).toLocaleTimeString();
return `
<div class="flex justify-between items-center bg-gray-50 p-3 rounded border">
<div>
<span class="font-medium">${process.display_name}</span>
<span class="text-sm text-gray-500 block">PID: ${process.pid} | Iniciado: ${startTime}</span>
</div>
<button class="text-red-500 hover:text-red-700 text-sm"
onclick="csharpLauncherManager.terminateProcess(${process.pid})">
Cerrar
</button>
</div>
`;
}).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);
}
}
clearExecutables() {
const grid = document.getElementById('csharp-executables-grid');
if (grid) {
grid.innerHTML = '<div class="col-span-full text-center py-8 text-gray-500">Selecciona un proyecto para ver los ejecutables</div>';
}
}
}
// 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() {
// TODO: Implementar editor de proyectos C#
alert('Editor de proyectos C# - Por implementar');
}
function openCSharpProjectInEditor(editor) {
if (!window.csharpLauncherManager?.currentProject) {
alert('Selecciona un proyecto primero');
return;
}
const projectId = window.csharpLauncherManager.currentProject.id;
if (editor === 'cursor') {
// Implementar apertura en Cursor
alert(`Abriendo proyecto ${projectId} en Cursor - Por implementar`);
} else if (editor === 'vs2022') {
// Implementar apertura en Visual Studio 2022
alert(`Abriendo proyecto ${projectId} en Visual Studio 2022 - Por implementar`);
}
}
function openCSharpProjectFolder() {
if (!window.csharpLauncherManager?.currentProject) {
alert('Selecciona un proyecto primero');
return;
}
// Implementar apertura de carpeta
alert('Abriendo carpeta del proyecto - Por implementar');
}
function copyCSharpProjectPath() {
if (!window.csharpLauncherManager?.currentProject) {
alert('Selecciona un proyecto primero');
return;
}
// Implementar copia de path
navigator.clipboard.writeText(window.csharpLauncherManager.currentProject.directory);
}
function openCSharpExecutableManager() {
// TODO: Implementar gestor de ejecutables
alert('Gestor de ejecutables C# - Por implementar');
}
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);
}
}
// Inicialización global
window.csharpLauncherManager = new CSharpLauncherManager();