ParamManagerScripts/templates/index.html

1531 lines
84 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Script Parameter Manager</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}?v=1.1">
</head>
<body class="bg-gray-100">
<!-- Settings Button -->
<div class="fixed top-4 right-4 z-50">
<button onclick="toggleSidebar()" class="bg-white p-2 rounded-full shadow-lg hover:bg-gray-100">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z">
</path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
</button>
</div>
<!-- Sidebar -->
<div class="overlay" onclick="toggleSidebar()"></div>
<div class="sidebar">
<div class="p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-bold">Configuración Global</h2>
<button onclick="toggleSidebar()" class="text-gray-500 hover:text-gray-700">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12">
</path>
</svg>
</button>
</div>
<!-- Level 1 Configuration -->
<div class="mb-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Configuración Base</h2>
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="toggleConfig('level1-content')">
Mostrar Configuración
</button>
</div>
<div id="level1-content" class="hidden">
<div id="level1-form"></div>
<div class="flex justify-end mt-4">
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="modifySchema(1)">
Modificar Esquema
</button>
</div>
</div>
</div>
<!-- Level 2 Configuration -->
<div class="mb-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Configuración del Scripts</h2>
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="toggleConfig('level2-content')">
Mostrar Configuración
</button>
</div>
<div id="level2-content" class="hidden">
<div id="level2-form"></div>
<div class="flex justify-end mt-4">
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="modifySchema(2)">
Modificar Esquema
</button>
</div>
</div>
</div>
<!-- Botón para detener el servidor -->
<div class="mt-8 pt-4 border-t border-gray-300">
<button class="w-full bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded shadow mb-2"
onclick="openMinicondaConsole()">
Abrir Miniconda Console
</button>
<button class="w-full bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded shadow"
onclick="shutdownServer()">
Detener Servidor
</button>
</div>
</div>
</div>
<!-- Main Content -->
<div class="container mx-auto px-4 py-8">
<!-- Tab Navigation -->
<div class="mb-8">
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-8">
<button id="config-tab" onclick="switchTab('config')"
class="tab-button active py-2 px-1 border-b-2 font-medium text-sm">
<span class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z">
</path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
Scripts de Configuración
</span>
</button>
<button id="launcher-tab" onclick="switchTab('launcher')"
class="tab-button py-2 px-1 border-b-2 font-medium text-sm">
<span class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z">
</path>
</svg>
Launcher GUI (Python)
</span>
</button>
<button id="csharp-tab" onclick="switchTab('csharp')"
class="tab-button py-2 px-1 border-b-2 font-medium text-sm">
<span class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0-1.125.504-1.125 1.125V11.25a9 9 0 00-9-9z">
</path>
</svg>
Launcher C#
</span>
</button>
<button id="python-tab" onclick="switchTab('python')"
class="tab-button py-2 px-1 border-b-2 font-medium text-sm">
<span class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M7 16h.01">
</path>
</svg>
Python Scripts
</span>
</button>
</nav>
</div>
</div>
<!-- Tab Content: Sistema de Configuración Actual -->
<div id="config-content" class="tab-content">
<!-- Script Group Selection -->
<div class="mb-8 bg-white p-6 rounded-lg shadow">
<h2 class="text-xl font-bold mb-4">Funciones a utilizar:</h2>
<div class="flex gap-2 items-center">
<select id="script-group" class="flex-1 p-2 border rounded mb-2">
{% for group in script_groups %}
<option value="{{ group.id }}" data-description="{{ group.description }}">{{ group.name }}
</option>
{% endfor %}
</select>
<button onclick="editGroupDescription()" class="bg-blue-500 text-white p-2 rounded mb-2">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z">
</path>
</svg>
</button>
<button onclick="openGroupInEditor('vscode', 'config', currentGroup)"
class="bg-blue-500 text-white p-2 rounded mb-2" id="vscode-config-btn"
title="Abrir grupo en VS Code">
<img src="{{ url_for('static', filename='icons/vscode.png') }}" class="w-5 h-5"
alt="VS Code Icon">
</button>
<!-- Nuevo botón para Cursor -->
<button onclick="openGroupInEditor('cursor', 'config', currentGroup)"
class="bg-blue-500 text-white p-2 rounded mb-2" id="cursor-config-btn"
title="Abrir grupo en Cursor">
<img src="{{ url_for('static', filename='icons/cursor.png') }}" class="w-5 h-5"
alt="Cursor Icon">
</button>
<!-- Botón para abrir carpeta del grupo -->
<button onclick="openGroupFolder('config', currentGroup)"
class="bg-green-500 text-white p-2 rounded mb-2" id="folder-config-btn"
title="Abrir carpeta del grupo">
📁
</button>
<!-- Botón para copiar path del grupo -->
<button onclick="copyGroupPath('config', currentGroup)"
class="bg-gray-500 text-white p-2 rounded mb-2" id="copy-path-config-btn"
title="Copiar path del grupo">
📋
</button>
</div>
<p id="group-description" class="text-gray-600 text-sm italic"></p>
<div class="text-xs text-gray-500 mt-2">
<span id="group-version"></span>
<span id="group-author"></span>
</div>
</div>
<!-- Working Directory -->
<div class="mb-8 bg-white p-6 rounded-lg shadow">
<h2 class="text-xl font-bold mb-4">Directorio de Trabajo</h2>
<div class="flex gap-4">
<div class="flex-1 flex gap-2">
<input type="text" id="working-directory" class="flex-1 p-2 border rounded bg-green-50">
<button class="bg-gray-500 text-white px-4 py-2 rounded" onclick="browseDirectory()">
Buscar
</button>
<button id="open-in-explorer-btn"
class="bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded"
title="Abrir directorio actual en el explorador de archivos">
Abrir Carpeta
</button>
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="setWorkingDirectory()">
Salvar
</button>
</div>
</div>
<!-- Add directory history dropdown -->
<div class="mt-2">
<select id="directory-history" class="w-full p-2 border rounded text-gray-600"
onchange="loadHistoryDirectory(this.value)">
<option value="">-- Directorios recientes --</option>
</select>
</div>
</div>
<!-- Level 3 Configuration -->
<div class="mb-8 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Configuración del Directorio</h2>
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="toggleConfig('level3-content')">
Ocultar Configuración
</button>
</div>
<div id="level3-content">
<div id="level3-form"></div>
<div class="flex justify-end mt-4">
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="modifySchema(3)">
Modificar Esquema
</button>
</div>
</div>
</div>
<!-- Scripts List -->
<div class="mb-8 bg-white p-6 rounded-lg shadow">
<h2 class="text-xl font-bold mb-4">Scripts Disponibles</h2>
<div id="scripts-list" class="space-y-4"></div>
</div>
</div>
<!-- Tab Content: Nuevo Launcher GUI -->
<div id="launcher-content" class="tab-content hidden">
<!-- Launcher Controls -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Launcher GUI - Scripts Python Independientes</h2>
<button onclick="openGroupEditor()"
class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600">
Gestionar Grupos
</button>
</div>
<!-- Group Selector -->
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Seleccionar Grupo de Scripts</label>
<div class="flex gap-2">
<div class="relative flex-1">
<select id="launcher-group-select" class="w-full p-3 border rounded-lg pl-12"
onchange="loadLauncherScripts()">
<option value="">-- Seleccionar Grupo --</option>
</select>
<div class="absolute left-3 top-1/2 transform -translate-y-1/2">
<div id="selected-group-icon"
class="w-6 h-6 bg-gray-200 rounded flex items-center justify-center text-sm">📁
</div>
</div>
</div>
<button
onclick="launcherManager.openGroupInEditor('vscode', 'launcher', launcherManager.currentGroup.id)"
class="bg-purple-500 text-white px-4 py-3 rounded-lg hover:bg-purple-600"
id="vscode-launcher-btn" style="display: none;" title="Abrir grupo en VS Code">
<img src="{{ url_for('static', filename='icons/vscode.png') }}" class="w-5 h-5"
alt="VS Code Icon">
</button>
<!-- Nuevo botón para Cursor -->
<button
onclick="launcherManager.openGroupInEditor('cursor', 'launcher', launcherManager.currentGroup.id)"
class="bg-purple-500 text-white px-4 py-3 rounded-lg hover:bg-purple-600"
id="cursor-launcher-btn" style="display: none;" title="Abrir grupo en Cursor">
<img src="{{ url_for('static', filename='icons/cursor.png') }}" class="w-5 h-5"
alt="Cursor Icon">
</button>
<!-- Botón para abrir carpeta del grupo launcher -->
<button onclick="launcherManager.openGroupFolder()"
class="bg-green-500 text-white px-4 py-3 rounded-lg hover:bg-green-600"
id="folder-launcher-btn" style="display: none;" title="Abrir carpeta del grupo">
📁
</button>
<!-- Botón para copiar path del grupo launcher -->
<button onclick="launcherManager.copyGroupPath()"
class="bg-gray-500 text-white px-4 py-3 rounded-lg hover:bg-gray-600"
id="copy-path-launcher-btn" style="display: none;" title="Copiar path del grupo">
📋
</button>
</div>
</div>
<!-- Category Filter -->
<div class="mb-4">
<h3 class="text-sm font-medium mb-2">Filtrar por Categoría</h3>
<div class="flex flex-wrap gap-2">
<button class="category-btn active px-3 py-1 rounded-full text-sm border" data-category="all"
onclick="filterByCategory('all')">
Todas
</button>
<button class="category-btn px-3 py-1 rounded-full text-sm border" data-category="Herramientas"
onclick="filterByCategory('Herramientas')">
🔧 Herramientas
</button>
<button class="category-btn px-3 py-1 rounded-full text-sm border" data-category="Análisis"
onclick="filterByCategory('Análisis')">
📊 Análisis
</button>
<button class="category-btn px-3 py-1 rounded-full text-sm border" data-category="Utilidades"
onclick="filterByCategory('Utilidades')">
Utilidades
</button>
</div>
</div>
</div>
<!-- Favorites Panel -->
<div id="favorites-panel" class="mb-6 bg-yellow-50 border border-yellow-200 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-semibold text-yellow-800">
Scripts Favoritos
</h3>
<span class="text-sm text-yellow-600" id="favorites-count">
0 favoritos
</span>
</div>
<div id="favorites-list" class="space-y-2">
<!-- Lista dinámica de favoritos -->
</div>
</div>
<!-- Scripts Grid -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Scripts Disponibles</h2>
<button onclick="openScriptManager()"
class="bg-purple-500 text-white px-4 py-2 rounded hover:bg-purple-600" id="manage-scripts-btn"
style="display: none;">
Gestionar Scripts
</button>
</div>
<div id="launcher-scripts-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Scripts cards dinámicos -->
</div>
</div>
<!-- Markdown Files Section -->
<div id="markdown-files-section" class="mb-6 bg-white p-6 rounded-lg shadow" style="display: none;">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">📄 Documentación (Markdown)</h2>
<span class="text-sm text-gray-500">Archivos .md en el directorio del grupo</span>
</div>
<div id="markdown-files-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
<!-- Markdown files cards dinámicos -->
</div>
</div>
<!-- History Panel -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4 cursor-pointer" onclick="toggleHistoryPanel()">
<div class="flex items-center">
<span id="history-toggle-icon" class="mr-2"></span>
<h3 class="text-lg font-semibold">📝 Historial Reciente</h3>
</div>
<button onclick="event.stopPropagation(); clearLauncherHistory()"
class="text-red-500 hover:text-red-700 text-sm">
Limpiar Historial
</button>
</div>
<div id="history-list" class="space-y-2 max-h-64 overflow-y-auto hidden">
<!-- Lista dinámica de historial -->
</div>
</div>
</div>
<!-- Tab Content: Launcher C# -->
<div id="csharp-content" class="tab-content hidden">
<!-- C# Project Controls -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Launcher C# - Proyectos Compilados</h2>
<button onclick="openCSharpProjectEditor()"
class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600"
onmousedown="if(!window.openCSharpProjectEditor) alert('Launcher C# cargando...')">
Gestionar Proyectos
</button>
</div>
<!-- Project Selector -->
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Seleccionar Proyecto C#</label>
<div class="flex gap-2">
<div class="relative flex-1">
<select id="csharp-project-select" class="w-full p-3 border rounded-lg pl-12"
onchange="loadCSharpExecutables()">
<option value="">-- Seleccionar Proyecto --</option>
</select>
<div class="absolute left-3 top-1/2 transform -translate-y-1/2">
<div id="selected-csharp-project-icon"
class="w-6 h-6 bg-gray-200 rounded flex items-center justify-center text-sm">🗂
</div>
</div>
</div>
<button onclick="openCSharpProjectInEditor('cursor')"
class="bg-purple-500 text-white px-4 py-3 rounded-lg hover:bg-purple-600"
id="cursor-csharp-btn" style="display: none;" title="Abrir proyecto en Cursor">
<img src="{{ url_for('static', filename='icons/cursor.png') }}" class="w-5 h-5"
alt="Cursor Icon">
</button>
<button onclick="openCSharpProjectInEditor('vs2022')"
class="bg-purple-500 text-white px-4 py-3 rounded-lg hover:bg-purple-600"
id="vs2022-csharp-btn" style="display: none;" title="Abrir proyecto en Visual Studio 2022">
💜
</button>
<button onclick="openCSharpProjectFolder()"
class="bg-green-500 text-white px-4 py-3 rounded-lg hover:bg-green-600"
id="folder-csharp-btn" style="display: none;" title="Abrir carpeta del proyecto">
📁
</button>
<button onclick="copyCSharpProjectPath()"
class="bg-gray-500 text-white px-4 py-3 rounded-lg hover:bg-gray-600"
id="copy-path-csharp-btn" style="display: none;" title="Copiar path del proyecto">
📋
</button>
</div>
</div>
<!-- Category Filter -->
<div class="mb-4">
<h3 class="text-sm font-medium mb-2">Filtrar por Categoría</h3>
<div class="flex flex-wrap gap-2">
<button class="csharp-category-btn active px-3 py-1 rounded-full text-sm border"
data-category="all" onclick="filterCSharpByCategory('all')">
Todas
</button>
<button class="csharp-category-btn px-3 py-1 rounded-full text-sm border"
data-category="Aplicaciones" onclick="filterCSharpByCategory('Aplicaciones')">
🖥 Aplicaciones
</button>
<button class="csharp-category-btn px-3 py-1 rounded-full text-sm border"
data-category="Herramientas" onclick="filterCSharpByCategory('Herramientas')">
🔧 Herramientas
</button>
<button class="csharp-category-btn px-3 py-1 rounded-full text-sm border" data-category="APIs"
onclick="filterCSharpByCategory('APIs')">
🌐 APIs
</button>
</div>
</div>
</div>
<!-- C# Favorites Panel -->
<div id="csharp-favorites-panel" class="mb-6 bg-blue-50 border border-blue-200 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-semibold text-blue-800">
Ejecutables Favoritos
</h3>
<span class="text-sm text-blue-600" id="csharp-favorites-count">
0 favoritos
</span>
</div>
<div id="csharp-favorites-list" class="space-y-2">
<!-- Lista dinámica de favoritos C# -->
</div>
</div>
<!-- C# Executables Grid -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Ejecutables Disponibles</h2>
<button onclick="openCSharpExecutableManager()"
class="bg-purple-500 text-white px-4 py-2 rounded hover:bg-purple-600"
id="manage-csharp-executables-btn" style="display: none;">
Gestionar Ejecutables
</button>
</div>
<div id="csharp-executables-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Executable cards dinámicos -->
</div>
</div>
<!-- Running Processes Panel -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">🔄 Procesos en Ejecución</h3>
<button onclick="refreshCSharpProcesses()" class="text-blue-500 hover:text-blue-700 text-sm">
Actualizar
</button>
</div>
<div id="csharp-running-processes" class="space-y-2">
<!-- Lista dinámica de procesos -->
</div>
</div>
</div>
<!-- Tab Content: Python Scripts -->
<div id="python-content" class="tab-content hidden">
<!-- Python Project Controls -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Python Scripts - MCP Servers & Background Scripts</h2>
<button onclick="openPythonProjectEditor()"
class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600"
onmousedown="if(!window.openPythonProjectEditor) alert('Python Launcher cargando...')">
Gestionar Proyectos
</button>
</div>
<!-- Project Selector -->
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Seleccionar Proyecto Python</label>
<div class="flex gap-2">
<div class="relative flex-1">
<select id="python-project-select" class="w-full p-3 border rounded-lg pl-12"
onchange="loadPythonScripts()">
<option value="">-- Seleccionar Proyecto --</option>
</select>
<div class="absolute left-3 top-1/2 transform -translate-y-1/2">
<div id="selected-python-project-icon"
class="w-6 h-6 bg-gray-200 rounded flex items-center justify-center text-sm">🐍
</div>
</div>
</div>
<button onclick="openPythonProjectInEditor('vscode')"
class="bg-blue-500 text-white px-4 py-3 rounded-lg hover:bg-blue-600" id="vscode-python-btn"
style="display: none;" title="Abrir proyecto en VS Code">
<img src="{{ url_for('static', filename='icons/vscode.png') }}" class="w-5 h-5"
alt="VS Code Icon">
</button>
<button onclick="openPythonProjectInEditor('cursor')"
class="bg-purple-500 text-white px-4 py-3 rounded-lg hover:bg-purple-600"
id="cursor-python-btn" style="display: none;" title="Abrir proyecto en Cursor">
<img src="{{ url_for('static', filename='icons/cursor.png') }}" class="w-5 h-5"
alt="Cursor Icon">
</button>
<button onclick="openPythonProjectFolder()"
class="bg-green-500 text-white px-4 py-3 rounded-lg hover:bg-green-600"
id="folder-python-btn" style="display: none;" title="Abrir carpeta del proyecto">
📁
</button>
<button onclick="copyPythonProjectPath()"
class="bg-gray-500 text-white px-4 py-3 rounded-lg hover:bg-gray-600"
id="copy-path-python-btn" style="display: none;" title="Copiar path del proyecto">
📋
</button>
</div>
</div>
<!-- Category Filter -->
<div class="mb-4">
<h3 class="text-sm font-medium mb-2">Filtrar por Categoría</h3>
<div class="flex flex-wrap gap-2">
<button class="python-category-btn active px-3 py-1 rounded-full text-sm border"
data-category="all" onclick="filterPythonByCategory('all')">
Todas
</button>
<button class="python-category-btn px-3 py-1 rounded-full text-sm border"
data-category="MCP Servers" onclick="filterPythonByCategory('MCP Servers')">
🔌 MCP Servers
</button>
<button class="python-category-btn px-3 py-1 rounded-full text-sm border"
data-category="Flask Apps" onclick="filterPythonByCategory('Flask Apps')">
🌐 Flask Apps
</button>
<button class="python-category-btn px-3 py-1 rounded-full text-sm border"
data-category="Scripts" onclick="filterPythonByCategory('Scripts')">
📜 Scripts
</button>
<button class="python-category-btn px-3 py-1 rounded-full text-sm border" data-category="Bots"
onclick="filterPythonByCategory('Bots')">
🤖 Bots
</button>
</div>
</div>
</div>
<!-- Python Favorites Panel -->
<div id="python-favorites-panel" class="mb-6 bg-green-50 border border-green-200 rounded-lg p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-semibold text-green-800">
Scripts Favoritos
</h3>
<span class="text-sm text-green-600" id="python-favorites-count">
0 favoritos
</span>
</div>
<div id="python-favorites-list" class="space-y-2">
<!-- Lista dinámica de favoritos Python -->
</div>
</div>
<!-- Python Scripts Grid -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Scripts Disponibles</h2>
<button onclick="openPythonScriptManager()"
class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
id="manage-python-scripts-btn" style="display: none;">
Gestionar Scripts
</button>
</div>
<div id="python-scripts-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Script cards dinámicos -->
</div>
</div>
<!-- Python Markdown Files Section -->
<div id="python-markdown-files-section" class="mb-6 bg-white p-6 rounded-lg shadow" style="display: none;">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">📄 Documentación (Markdown)</h2>
<span class="text-sm text-gray-500">Archivos .md en el directorio del proyecto</span>
</div>
<div id="python-markdown-files-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
<!-- Markdown files cards dinámicos -->
</div>
</div>
<!-- Running Processes Panel -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">🔄 Procesos en Ejecución</h3>
<button onclick="refreshPythonProcesses()" class="text-blue-500 hover:text-blue-700 text-sm">
Actualizar
</button>
</div>
<div id="python-running-processes" class="space-y-2">
<!-- Lista dinámica de procesos -->
</div>
</div>
<!-- History Panel -->
<div class="mb-6 bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">📋 Historial de Ejecuciones</h3>
<button onclick="clearPythonHistory()" class="text-red-500 hover:text-red-700 text-sm">
Limpiar Historial
</button>
</div>
<div id="python-history-list" class="space-y-2 max-h-64 overflow-y-auto">
<!-- Lista dinámica de historial -->
</div>
</div>
</div>
<!-- Modal: Editor de Proyectos C# -->
<div id="csharp-project-editor-modal"
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg shadow-xl w-full max-w-6xl mx-4 max-h-[90vh] overflow-hidden">
<div class="flex justify-between items-center p-6 border-b">
<h2 class="text-xl font-bold">Gestión de Proyectos C#</h2>
<button onclick="closeCSharpProjectEditor()" class="text-gray-500 hover:text-gray-700">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<div class="flex h-[70vh]">
<!-- Lista de Proyectos Existentes -->
<div class="w-1/2 p-6 border-r overflow-y-auto">
<h3 class="text-lg font-semibold mb-4">Proyectos Existentes</h3>
<div id="csharp-existing-projects" class="space-y-3">
<!-- Lista dinámica de proyectos -->
</div>
</div>
<!-- Formulario de Proyecto -->
<div class="w-1/2 p-6 overflow-y-auto">
<h3 class="text-lg font-semibold mb-4">Agregar/Editar Proyecto</h3>
<form id="csharp-project-form" class="space-y-4">
<input type="hidden" id="csharp-project-id">
<!-- Nombre del Proyecto -->
<div>
<label class="block text-sm font-medium mb-1">Nombre del Proyecto *</label>
<input type="text" id="csharp-project-name" class="w-full p-2 border rounded-lg"
placeholder="Mi Aplicación C#" required>
</div>
<!-- Descripción -->
<div>
<label class="block text-sm font-medium mb-1">Descripción</label>
<textarea id="csharp-project-description" class="w-full p-2 border rounded-lg h-20"
placeholder="Descripción del proyecto"></textarea>
</div>
<!-- Directorio -->
<div>
<label class="block text-sm font-medium mb-1">Directorio del Proyecto *</label>
<div class="flex gap-2">
<input type="text" id="csharp-project-directory"
class="flex-1 p-2 border rounded-lg" placeholder="C:\Proyectos\MiApp" required>
<button type="button" onclick="browseCSharpProjectDirectory()"
class="bg-gray-500 text-white px-3 py-2 rounded-lg hover:bg-gray-600">
📁
</button>
</div>
</div>
<!-- Categoría -->
<div>
<label class="block text-sm font-medium mb-1">Categoría</label>
<select id="csharp-project-category" class="w-full p-2 border rounded-lg">
<option value="Aplicaciones">🖥 Aplicaciones</option>
<option value="Herramientas">🔧 Herramientas</option>
<option value="Análisis">📊 Análisis</option>
<option value="Desarrollo">💻 Desarrollo</option>
<option value="APIs">🌐 APIs</option>
<option value="Otros">📁 Otros</option>
</select>
</div>
<!-- Versión -->
<div>
<label class="block text-sm font-medium mb-1">Versión</label>
<input type="text" id="csharp-project-version" class="w-full p-2 border rounded-lg"
placeholder="1.0" value="1.0">
</div>
<!-- Autor -->
<div>
<label class="block text-sm font-medium mb-1">Autor</label>
<input type="text" id="csharp-project-author" class="w-full p-2 border rounded-lg"
placeholder="Nombre del desarrollador">
</div>
<!-- Versión .NET -->
<div>
<label class="block text-sm font-medium mb-1">Versión .NET</label>
<input type="text" id="csharp-project-dotnet-version"
class="w-full p-2 border rounded-lg"
placeholder="6.0, Framework 4.8, Core 3.1, etc.">
</div>
<!-- Tags -->
<div>
<label class="block text-sm font-medium mb-1">Tags</label>
<input type="text" id="csharp-project-tags" class="w-full p-2 border rounded-lg"
placeholder="winforms, wpf, console, api (separados por comas)">
</div>
<!-- Botones -->
<div class="flex justify-between pt-4">
<button type="button" onclick="deleteCSharpProject()"
class="bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600"
id="delete-csharp-project-btn">
Eliminar Proyecto
</button>
<div class="space-x-2">
<button type="button" onclick="closeCSharpProjectEditor()"
class="bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600">
Cancelar
</button>
<button type="button" onclick="saveCSharpProject()"
class="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600">
Guardar Proyecto
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Logs (común para ambos sistemas) -->
<div class="bg-white p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold">Logs</h2>
<button class="bg-red-500 text-white px-4 py-2 rounded" onclick="clearLogs()">
Limpiar
</button>
</div>
<div id="log-area"
class="bg-gray-100 p-4 rounded h-64 overflow-y-auto font-mono text-sm whitespace-pre-wrap">
</div>
</div>
</div>
<!-- Schema Editor Modal (existente) -->
<div id="schema-editor" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center">
<div class="modal-content bg-white rounded-lg shadow-lg max-h-screen overflow-auto">
<div class="modal-header">
<div class="flex justify-between items-center">
<h3 class="text-xl font-bold">Editor de Esquema</h3>
<div class="flex gap-4">
<button onclick="document.getElementById('schema-editor').classList.add('hidden')"
class="bg-gray-500 text-white px-4 py-2 rounded">
Cancelar
</button>
<button onclick="saveSchema()" class="bg-blue-500 text-white px-4 py-2 rounded">
Guardar
</button>
</div>
</div>
<div class="flex mt-4" id="editor-tabs">
<button id="visual-tab" class="px-4 py-2 border-b-2"
onclick="switchEditorMode('visual')">Visual</button>
<button id="json-tab" class="px-4 py-2 border-b-2" onclick="switchEditorMode('json')">JSON</button>
</div>
</div>
<div class="p-4">
<div id="visual-editor" class="hidden">
<div id="schema-fields"></div>
<button onclick="addSchemaField()" class="mt-4 bg-green-500 text-white px-4 py-2 rounded">Agregar
Campo</button>
</div>
<textarea id="json-editor" class="w-full h-96 font-mono p-2 border rounded"></textarea>
<input type="hidden" id="schema-level">
</div>
<div class="modal-footer">
<div class="flex justify-end gap-4">
<button onclick="document.getElementById('schema-editor').classList.add('hidden')"
class="bg-gray-500 text-white px-4 py-2 rounded">
Cancelar
</button>
<button onclick="saveSchema()" class="bg-blue-500 text-white px-4 py-2 rounded">
Guardar
</button>
</div>
</div>
</div>
</div>
<!-- Script Details Editor Modal (existente) -->
<div id="script-editor-modal"
class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50">
<div class="modal-content bg-white rounded-lg shadow-lg w-full max-w-lg max-h-[90vh] overflow-auto">
<div class="modal-header sticky top-0 bg-white border-b p-4">
<div class="flex justify-between items-center">
<h3 class="text-xl font-bold">Editar Detalles del Script</h3>
<button onclick="closeScriptEditorModal()"
class="text-gray-500 hover:text-gray-700">&times;</button>
</div>
</div>
<div class="p-6 space-y-4">
<input type="hidden" id="edit-script-group">
<input type="hidden" id="edit-script-filename">
<div>
<label class="block text-sm font-bold mb-1">Nombre del Archivo</label>
<p id="edit-script-filename-display" class="text-sm text-gray-600 bg-gray-100 p-2 rounded border">
</p>
</div>
<div>
<label for="edit-script-display-name" class="block text-sm font-bold mb-2">Nombre a Mostrar</label>
<input type="text" id="edit-script-display-name" class="w-full p-2 border rounded">
</div>
<div>
<label for="edit-script-short-description" class="block text-sm font-bold mb-2">Descripción
Corta</label>
<input type="text" id="edit-script-short-description" class="w-full p-2 border rounded">
</div>
<div>
<label for="edit-script-long-description" class="block text-sm font-bold mb-2">Descripción Larga /
Ayuda</label>
<textarea id="edit-script-long-description" class="w-full p-2 border rounded" rows="5"></textarea>
<p class="text-xs text-gray-500 mt-1">Usa Markdown. Doble Enter para párrafo nuevo, dos espacios +
Enter para salto de línea simple.</p>
</div>
<div class="flex items-center">
<input type="checkbox" id="edit-script-hidden" class="form-checkbox h-5 w-5 mr-2">
<label for="edit-script-hidden" class="text-sm font-bold">Ocultar script (no se podrá ejecutar desde
la UI)</label>
</div>
</div>
<div class="modal-footer sticky bottom-0 bg-white border-t p-4 flex justify-end gap-4">
<button onclick="closeScriptEditorModal()"
class="bg-gray-500 text-white px-4 py-2 rounded">Cancelar</button>
<button onclick="saveScriptDetails()" class="bg-blue-500 text-white px-4 py-2 rounded">Guardar
Cambios</button>
</div>
</div>
</div>
<!-- Group Editor Modal (NUEVO) -->
<div id="group-editor-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-screen overflow-y-auto">
<div class="p-6">
<h3 class="text-xl font-semibold mb-6">Gestionar Grupos de Scripts GUI</h3>
<!-- Lista de grupos existentes -->
<div class="mb-6">
<h4 class="font-medium mb-3">Grupos Existentes</h4>
<div id="existing-groups-list" class="space-y-2 max-h-40 overflow-y-auto border rounded p-2">
<!-- Lista dinámica -->
</div>
</div>
<!-- Formulario de edición -->
<form id="group-form" class="space-y-4">
<!-- El ID se genera automáticamente basado en el nombre -->
<div>
<label class="block text-sm font-medium mb-1">Nombre</label>
<input type="text" id="group-name" class="w-full p-2 border rounded" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Descripción</label>
<textarea id="group-description" class="w-full p-2 border rounded h-20"></textarea>
</div>
<div class="grid grid-cols-3 gap-4">
<div>
<label class="block text-sm font-medium mb-1">Categoría</label>
<select id="group-category" class="w-full p-2 border rounded">
<option value="Herramientas">🔧 Herramientas</option>
<option value="Análisis">📊 Análisis</option>
<option value="Utilidades"> Utilidades</option>
<option value="Desarrollo">💻 Desarrollo</option>
<option value="Visualización">📈 Visualización</option>
<option value="Otros">📁 Otros</option>
</select>
</div>
<div>
<label class="block text-sm font-medium mb-1">Versión</label>
<input type="text" id="group-version" class="w-full p-2 border rounded" value="1.0">
</div>
<div>
<label class="block text-sm font-medium mb-1">Entorno Python</label>
<select id="group-python-env" class="w-full p-2 border rounded">
<option value="base">Cargando...</option>
</select>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-1">Directorio</label>
<div class="flex gap-2">
<input type="text" id="group-directory" class="flex-1 p-2 border rounded" required>
<button type="button" onclick="browseGroupDirectory()"
class="bg-gray-500 text-white px-4 py-2 rounded">
Explorar
</button>
</div>
</div>
<div class="flex justify-end gap-3 pt-4">
<button type="button" onclick="closeGroupEditor()"
class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cancelar
</button>
<button type="button" onclick="deleteGroup()"
class="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600" id="delete-group-btn"
style="display: none;">
Eliminar
</button>
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Guardar
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Script Manager Modal (NUEVO) -->
<div id="script-manager-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-screen overflow-y-auto">
<div class="p-6">
<h3 class="text-xl font-semibold mb-6">Gestionar Scripts del Grupo</h3>
<p class="text-gray-600 mb-4" id="script-manager-group-info">Selecciona un grupo para gestionar sus
scripts</p>
<!-- Lista de scripts -->
<div class="space-y-3" id="script-manager-list">
<!-- Lista dinámica de scripts -->
</div>
<div class="flex justify-end gap-3 pt-4 mt-6 border-t">
<button type="button" onclick="closeScriptManager()"
class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cerrar
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Script Metadata Editor Modal (NUEVO) -->
<div id="script-metadata-editor-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-lg w-full max-h-screen overflow-y-auto">
<div class="p-6">
<h3 class="text-lg font-semibold mb-4">Editar Metadatos del Script</h3>
<form id="script-metadata-form" class="space-y-4">
<input type="hidden" id="edit-meta-group-id">
<input type="hidden" id="edit-meta-script-name">
<div>
<label class="block text-sm font-bold mb-1">Nombre del Archivo</label>
<p id="edit-meta-filename-display"
class="text-sm text-gray-600 bg-gray-100 p-2 rounded border"></p>
</div>
<div>
<label for="edit-meta-display-name" class="block text-sm font-bold mb-2">Nombre a
Mostrar</label>
<input type="text" id="edit-meta-display-name" class="w-full p-2 border rounded" required>
</div>
<div>
<label for="edit-meta-description" class="block text-sm font-bold mb-2">Descripción
Corta</label>
<input type="text" id="edit-meta-description" class="w-full p-2 border rounded">
</div>
<div>
<label for="edit-meta-long-description" class="block text-sm font-bold mb-2">Descripción
Larga / Ayuda</label>
<textarea id="edit-meta-long-description" class="w-full p-2 border rounded"
rows="5"></textarea>
<p class="text-xs text-gray-500 mt-1">Usa Markdown. Doble Enter para párrafo nuevo, dos
espacios + Enter para salto de línea simple.</p>
</div>
<div class="flex items-center">
<input type="checkbox" id="edit-meta-hidden" class="form-checkbox h-5 w-5 mr-2">
<label for="edit-meta-hidden" class="text-sm font-bold">Ocultar script (no aparecerá en la
lista de ejecución)</label>
</div>
<div class="flex justify-end gap-3 pt-4">
<button type="button" onclick="closeScriptMetadataEditor()"
class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cancelar
</button>
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Guardar Cambios
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Script Arguments Modal (NUEVO) -->
<div id="script-args-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-md w-full">
<div class="p-6">
<h3 class="text-lg font-semibold mb-4">Argumentos del Script</h3>
<div id="script-info" class="mb-4 p-3 bg-gray-50 rounded">
<div class="font-medium" id="script-display-name"></div>
<div class="text-sm text-gray-600" id="script-args-description"></div>
</div>
<div class="space-y-3">
<div>
<label class="block text-sm font-medium mb-1">
Argumentos de Línea de Comandos
</label>
<textarea id="script-args-input" class="w-full p-2 border rounded h-20"
placeholder="--input data.xlsx --output results.csv"></textarea>
<p class="text-xs text-gray-500 mt-1">
Separar argumentos con espacios. Usar comillas para valores con espacios.
</p>
</div>
<div>
<label class="block text-sm font-medium mb-1">
Directorio de Ejecución
</label>
<div class="flex gap-2">
<input type="text" id="script-working-dir" class="flex-1 p-2 border rounded"
placeholder="Por defecto: directorio del script">
<button type="button" onclick="browseWorkingDirectory()"
class="bg-gray-500 text-white px-3 py-2 rounded text-sm">
📁
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-1">
Tipo de Ejecución
</label>
<div class="flex gap-2">
<label class="flex items-center">
<input type="radio" name="execution-type" value="false" checked class="mr-2">
<span class="text-sm">🖥 Con Log (python.exe)</span>
</label>
<label class="flex items-center">
<input type="radio" name="execution-type" value="true" class="mr-2">
<span class="text-sm">🚀 Sin Log (pythonw.exe)</span>
</label>
</div>
<p class="text-xs text-gray-500 mt-1">
Con Log: Muestra la salida del script. Sin Log: No muestra ventana de consola.
</p>
</div>
</div>
<div class="flex justify-end gap-3 mt-6">
<button onclick="closeArgsModal()" class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cancelar
</button>
<button onclick="executeWithArgs()"
class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Ejecutar Script
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Script Description Modal (NUEVO) -->
<div id="script-description-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[80vh] overflow-hidden">
<div class="p-6 border-b">
<div class="flex justify-between items-start">
<div>
<h3 class="text-lg font-semibold" id="desc-modal-script-name">Descripción del Script</h3>
<p class="text-sm text-gray-600" id="desc-modal-script-file"></p>
</div>
<button onclick="closeDescriptionModal()"
class="text-gray-500 hover:text-gray-700 text-2xl">&times;</button>
</div>
</div>
<div class="p-6 overflow-y-auto max-h-[60vh]">
<div id="script-description-content" class="prose prose-sm max-w-none">
<!-- Contenido markdown renderizado -->
</div>
</div>
<div class="p-4 border-t bg-gray-50 flex justify-end">
<button onclick="closeDescriptionModal()"
class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600">
Cerrar
</button>
</div>
</div>
</div>
</div>
<!-- Markdown Viewer Modal (NUEVO) -->
<div id="markdown-viewer-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-hidden">
<div class="p-6 border-b">
<div class="flex justify-between items-start">
<div>
<h3 class="text-lg font-semibold" id="markdown-viewer-title">Documento Markdown</h3>
<p class="text-sm text-gray-600" id="markdown-viewer-path"></p>
</div>
<button onclick="closeMarkdownViewer()"
class="text-gray-500 hover:text-gray-700 text-2xl">&times;</button>
</div>
</div>
<div class="p-6 overflow-y-auto max-h-[75vh]">
<div id="markdown-viewer-content" class="prose prose-lg max-w-none">
<!-- Contenido markdown renderizado -->
</div>
</div>
<div class="p-4 border-t bg-gray-50 flex justify-end">
<button onclick="closeMarkdownViewer()"
class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600">
Cerrar
</button>
</div>
</div>
</div>
</div>
<!-- C# Executable Manager Modal -->
<div id="csharp-executable-manager" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-hidden">
<div class="p-6 border-b">
<div class="flex justify-between items-center">
<h3 class="text-lg font-semibold">Gestionar Ejecutables C#</h3>
<button onclick="closeCSharpExecutableManager()"
class="text-gray-500 hover:text-gray-700 text-2xl">&times;</button>
</div>
<p class="text-sm text-gray-600 mt-1">Edita la visibilidad, descripciones y argumentos de los
ejecutables</p>
</div>
<div class="p-6 overflow-y-auto max-h-[75vh]">
<div id="csharp-executable-list">
<!-- Lista dinámica de ejecutables -->
</div>
</div>
<div class="p-4 border-t bg-gray-50 flex justify-end">
<button onclick="closeCSharpExecutableManager()"
class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600">
Cerrar
</button>
</div>
</div>
</div>
</div>
<!-- Python Project Editor Modal -->
<div id="python-project-editor-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-screen overflow-y-auto">
<div class="p-6">
<h3 class="text-xl font-semibold mb-6">Gestionar Proyectos Python</h3>
<!-- Lista de proyectos existentes -->
<div class="mb-6">
<h4 class="font-medium mb-3">Proyectos Existentes</h4>
<div id="existing-python-projects-list"
class="space-y-2 max-h-40 overflow-y-auto border rounded p-2">
<!-- Lista dinámica -->
</div>
</div>
<!-- Formulario de edición -->
<form id="python-project-form" class="space-y-4"
onsubmit="event.preventDefault(); savePythonProject();">
<!-- El ID se genera automáticamente -->
<div>
<label class="block text-sm font-medium mb-1">Nombre</label>
<input type="text" id="python-project-name" class="w-full p-2 border rounded" required>
</div>
<div>
<label class="block text-sm font-medium mb-1">Descripción</label>
<textarea id="python-project-description" class="w-full p-2 border rounded h-20"></textarea>
</div>
<div class="grid grid-cols-3 gap-4">
<div>
<label class="block text-sm font-medium mb-1">Categoría</label>
<select id="python-project-category" class="w-full p-2 border rounded">
<option value="MCP Servers">🔗 MCP Servers</option>
<option value="Flask Apps">🌐 Flask Apps</option>
<option value="Scripts">📝 Scripts</option>
<option value="Bots">🤖 Bots</option>
<option value="Data Processing">📊 Data Processing</option>
<option value="Otros">📁 Otros</option>
</select>
</div>
<div>
<label class="block text-sm font-medium mb-1">Versión</label>
<input type="text" id="python-project-version" class="w-full p-2 border rounded"
value="1.0">
</div>
<div>
<label class="block text-sm font-medium mb-1">Entorno Python</label>
<select id="python-project-python-env" class="w-full p-2 border rounded">
<option value="base">base</option>
</select>
</div>
</div>
<div>
<label class="block text-sm font-medium mb-1">Directorio</label>
<div class="flex gap-2">
<input type="text" id="python-project-directory" class="flex-1 p-2 border rounded"
required>
<button type="button" onclick="browsePythonProjectDirectory()"
class="bg-gray-500 text-white px-4 py-2 rounded">
Explorar
</button>
</div>
</div>
<div class="flex justify-end gap-3 pt-4">
<button type="button" onclick="closePythonProjectEditor()"
class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cancelar
</button>
<button type="button" onclick="deletePythonProject()"
class="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600"
id="delete-python-project-btn" style="display: none;">
Eliminar
</button>
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Guardar
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Python Script Manager Modal -->
<div id="python-script-manager-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-screen overflow-y-auto">
<div class="p-6">
<h3 class="text-xl font-semibold mb-6">Gestionar Scripts del Proyecto</h3>
<p class="text-gray-600 mb-4" id="python-script-manager-project-info">Selecciona un proyecto para
gestionar sus scripts</p>
<!-- Lista de scripts -->
<div class="space-y-3" id="python-script-manager-list">
<!-- Lista dinámica de scripts -->
</div>
<div class="flex justify-end gap-3 pt-4 mt-6 border-t">
<button type="button" onclick="closePythonScriptManager()"
class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cerrar
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Python Script Metadata Editor Modal -->
<div id="python-script-metadata-editor-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-lg w-full max-h-screen overflow-y-auto">
<div class="p-6">
<h3 class="text-lg font-semibold mb-4">Editar Metadatos del Script Python</h3>
<form id="python-script-metadata-form" class="space-y-4"
onsubmit="event.preventDefault(); savePythonScriptMetadata();">
<input type="hidden" id="edit-python-meta-project-id">
<input type="hidden" id="edit-python-meta-script-name">
<div>
<label class="block text-sm font-bold mb-1">Nombre del Archivo</label>
<p id="edit-python-meta-filename-display"
class="text-sm text-gray-600 bg-gray-100 p-2 rounded border"></p>
</div>
<div>
<label for="edit-python-meta-display-name" class="block text-sm font-bold mb-2">Nombre a
Mostrar</label>
<input type="text" id="edit-python-meta-display-name" class="w-full p-2 border rounded"
required>
</div>
<div>
<label for="edit-python-meta-description" class="block text-sm font-bold mb-2">Descripción
Corta</label>
<input type="text" id="edit-python-meta-description" class="w-full p-2 border rounded">
</div>
<div>
<label for="edit-python-meta-long-description"
class="block text-sm font-bold mb-2">Descripción Larga / Ayuda</label>
<textarea id="edit-python-meta-long-description" class="w-full p-2 border rounded"
rows="5"></textarea>
<p class="text-xs text-gray-500 mt-1">Usa Markdown. Doble Enter para párrafo nuevo, dos
espacios + Enter para salto de línea simple.</p>
</div>
<div class="flex items-center">
<input type="checkbox" id="edit-python-meta-hidden" class="form-checkbox h-5 w-5 mr-2">
<label for="edit-python-meta-hidden" class="text-sm font-bold">Ocultar script (no aparecerá
en la lista de ejecución)</label>
</div>
<div class="flex justify-end gap-3 pt-4">
<button type="button" onclick="closePythonScriptMetadataEditor()"
class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cancelar
</button>
<button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Guardar Cambios
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Python Script Description Modal -->
<div id="python-script-description-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[80vh] overflow-hidden">
<div class="p-6 border-b">
<div class="flex justify-between items-start">
<div>
<h3 class="text-lg font-semibold" id="python-desc-modal-script-name">Descripción del Script
</h3>
<p class="text-sm text-gray-600" id="python-desc-modal-script-file"></p>
</div>
<button onclick="closePythonScriptDescription()"
class="text-gray-500 hover:text-gray-700 text-2xl">&times;</button>
</div>
</div>
<div class="p-6 overflow-y-auto max-h-[60vh]">
<div id="python-script-description-content" class="prose prose-sm max-w-none">
<!-- Contenido markdown renderizado -->
</div>
</div>
<div class="p-4 border-t bg-gray-50 flex justify-end">
<button onclick="closePythonScriptDescription()"
class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600">
Cerrar
</button>
</div>
</div>
</div>
</div>
<!-- Python Markdown Viewer Modal -->
<div id="python-markdown-viewer-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-hidden">
<div class="p-6 border-b">
<div class="flex justify-between items-start">
<div>
<h3 class="text-lg font-semibold" id="python-markdown-viewer-title">Documento Markdown</h3>
<p class="text-sm text-gray-600" id="python-markdown-viewer-path"></p>
</div>
<button onclick="closePythonMarkdownViewer()"
class="text-gray-500 hover:text-gray-700 text-2xl">&times;</button>
</div>
</div>
<div class="p-6 overflow-y-auto max-h-[75vh]">
<div id="python-markdown-viewer-content" class="prose prose-lg max-w-none">
<!-- Contenido markdown renderizado -->
</div>
</div>
<div class="p-4 border-t bg-gray-50 flex justify-end">
<button onclick="closePythonMarkdownViewer()"
class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600">
Cerrar
</button>
</div>
</div>
</div>
</div>
<!-- Python Script Options Modal -->
<div id="python-script-options-modal" class="hidden fixed inset-0 bg-gray-600 bg-opacity-50 z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white rounded-lg shadow-xl max-w-md w-full">
<div class="p-6">
<h3 class="text-lg font-semibold mb-4">Opciones de Ejecución - Python</h3>
<div id="python-script-info" class="mb-4 p-3 bg-gray-50 rounded">
<div class="font-medium" id="python-script-display-name"></div>
<div class="text-sm text-gray-600" id="python-script-description"></div>
</div>
<div class="space-y-3">
<div>
<label class="block text-sm font-medium mb-1">
Argumentos de Línea de Comandos
</label>
<textarea id="python-script-args-input" class="w-full p-2 border rounded h-20"
placeholder="--port 8080 --debug"></textarea>
<p class="text-xs text-gray-500 mt-1">
Separar argumentos con espacios. Usar comillas para valores con espacios.
</p>
</div>
<div>
<label class="block text-sm font-medium mb-1">
Tipo de Ejecución
</label>
<div class="flex gap-2">
<label class="flex items-center">
<input type="radio" name="python-execution-type" value="false" checked class="mr-2">
<span class="text-sm">🖥 Normal</span>
</label>
<label class="flex items-center">
<input type="radio" name="python-execution-type" value="true" class="mr-2">
<span class="text-sm">🚀 Background</span>
</label>
</div>
<p class="text-xs text-gray-500 mt-1">
Normal: Ejecuta y muestra salida. Background: Para servidores MCP, Flask apps, etc.
</p>
</div>
</div>
<div class="flex justify-end gap-3 mt-6">
<button onclick="closePythonScriptOptions()"
class="px-4 py-2 text-gray-600 hover:text-gray-800">
Cancelar
</button>
<button onclick="executePythonScriptWithOptions()"
class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Ejecutar Script
</button>
</div>
</div>
</div>
</div>
</div>
<script src="https://unpkg.com/markdown-it@14.1.0/dist/markdown-it.min.js"></script>
<script src="{{ url_for('static', filename='js/scripts.js') }}" defer></script>
<script src="{{ url_for('static', filename='js/launcher.js') }}" defer></script>
<script src="{{ url_for('static', filename='js/csharp_launcher.js') }}" defer></script>
<script src="{{ url_for('static', filename='js/python_launcher.js') }}" defer></script>
<script>
// Inicializar markdown-it globalmente
window.markdownit = window.markdownit || markdownit;
window.addEventListener('load', () => {
console.log('Window loaded, initializing app...');
if (typeof initializeApp === 'function') {
initializeApp().catch(console.error);
} else {
console.error('initializeApp function not found');
}
});
</script>
</body>
</html>