Se añadió una nueva ruta API para buscar archivos mediante un diálogo de selección, permitiendo al usuario elegir archivos desde su sistema. Además, se actualizaron los archivos de configuración JSON para incluir nuevos parámetros relacionados con el directorio de Obsidian y se mejoró la interfaz de usuario para manejar la selección de archivos, integrando un nuevo botón de búsqueda en los campos de entrada.
This commit is contained in:
parent
c8141deb63
commit
c37e485fd3
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
Puedes usar .doc\MemoriaDeEvolucion.md para obtener un contexto de las ultimas modificaciones y conceptos sobre este proyecto. Quisiera que con los conocimientos importantes y desiciones importantes adquiridas en cada modificacion los agregues a MemoriaDeEvolucion.md manteniendo el estilo que ya tenemos de texto simple sin demasiado codigo y una semantica resumida.
|
|
@ -0,0 +1,60 @@
|
|||
# Memoria de Evolución - ParamManagerScripts
|
||||
|
||||
## Descripción Base del Proyecto
|
||||
|
||||
**ParamManagerScripts** es un sistema de gestión y ejecución de scripts que proporciona una interfaz web para organizar y ejecutar scripts de diferentes tipos (Python, C#, etc.) de manera ordenada y controlada.
|
||||
|
||||
### Funcionalidad Principal
|
||||
|
||||
#### 1. Sistema de Configuración Jerárquica
|
||||
- **Nivel 1 (Global)**: Parámetros compartidos por todos los scripts (`data/data.json`)
|
||||
- **Nivel 2 (Grupo)**: Configuración específica de cada grupo de scripts (`script_config.json`)
|
||||
- **Nivel 3 (Trabajo)**: Parámetros específicos del directorio de trabajo (`work_dir.json`)
|
||||
|
||||
Esto esta definido en .doc\backend_setup.md
|
||||
|
||||
#### 2. Gestión de Scripts por Categorías
|
||||
- **Scripts de Configuración**: Scripts Python tradicionales organizados en grupos
|
||||
- **Launcher GUI**: Scripts Python con interfaz gráfica
|
||||
- **Proyectos C#**: Ejecutables y proyectos .NET
|
||||
- **Proyectos Python**: Scripts Python especializados
|
||||
|
||||
#### 3. Características del Frontend
|
||||
- Interfaz web accesible via `http://127.0.0.1:5000/`
|
||||
- Panel de logs en tiempo real con WebSocket
|
||||
- Gestión de directorios de trabajo por grupo
|
||||
- Integración con editores (VS Code, Cursor, Visual Studio)
|
||||
- Icono de bandeja del sistema para acceso rápido
|
||||
|
||||
#### 4. Sistema de Launchers
|
||||
- **Launcher General**: Para scripts Python con GUI
|
||||
- **Launcher C#**: Gestión de proyectos y ejecutables .NET
|
||||
- **Launcher Python**: Scripts Python especializados con gestión de entornos
|
||||
|
||||
#### 5. Servicios Compartidos
|
||||
- **ExcelService**: Manipulación de archivos Excel
|
||||
- **LanguageService**: Detección de idiomas
|
||||
- **LLMService**: Integración con modelos de IA (OpenAI, Groq, Claude, etc.)
|
||||
|
||||
Esto esta definido en .doc\backend_setup.md
|
||||
|
||||
### Arquitectura Técnica
|
||||
|
||||
- **Backend**: Flask con WebSocket para comunicación en tiempo real
|
||||
- **Frontend**: HTML/CSS/JavaScript con comunicación AJAX
|
||||
- **Configuración**: Sistema de archivos JSON con validación por esquemas
|
||||
- **Ejecución**: Subprocesos controlados con logging centralizado
|
||||
- **Codificación**: UTF-8 obligatorio para evitar problemas de caracteres
|
||||
|
||||
### Concepto Clave: Orientación a Directorios de Trabajo
|
||||
|
||||
El sistema está diseñado para trabajar con directorios específicos donde los scripts procesan archivos. Cada grupo puede tener su directorio de trabajo configurado, y los scripts acceden a la configuración consolidada a través de `load_configuration()` que combina los tres niveles de configuración.
|
||||
|
||||
---
|
||||
|
||||
## Historial de Cambios
|
||||
|
||||
### [Fecha de Creación] - Descripción Base
|
||||
- Documentación inicial del sistema ParamManagerScripts
|
||||
- Descripción de la arquitectura y funcionalidades principales
|
||||
- Establecimiento de la estructura de memoria de evolución
|
34
app.py
34
app.py
|
@ -244,6 +244,40 @@ def browse_directories():
|
|||
return jsonify({"status": "cancelled"})
|
||||
|
||||
|
||||
@app.route("/api/browse-files")
|
||||
def browse_files():
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
|
||||
# Obtener el path inicial
|
||||
current_path = request.args.get("current_path")
|
||||
initial_dir = os.path.dirname(os.path.abspath(__file__)) # Default
|
||||
if current_path:
|
||||
if os.path.isdir(current_path):
|
||||
initial_dir = current_path
|
||||
elif os.path.isfile(current_path):
|
||||
initial_dir = os.path.dirname(current_path)
|
||||
|
||||
# Crear y configurar la ventana principal de tkinter
|
||||
root = tk.Tk()
|
||||
root.attributes("-topmost", True) # Mantener la ventana siempre arriba
|
||||
root.withdraw()
|
||||
|
||||
# Abrir el diálogo de selección de archivo
|
||||
filepath = filedialog.askopenfilename(
|
||||
initialdir=initial_dir,
|
||||
title="Seleccionar Archivo",
|
||||
filetypes=(("All files", "*.*"),),
|
||||
)
|
||||
|
||||
# Destruir la ventana de tkinter
|
||||
root.destroy()
|
||||
|
||||
if filepath:
|
||||
return jsonify({"status": "success", "path": filepath})
|
||||
return jsonify({"status": "cancelled"})
|
||||
|
||||
|
||||
@app.route("/api/logs", methods=["GET", "DELETE"])
|
||||
def handle_logs():
|
||||
if request.method == "GET":
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ObsideanDir": {
|
||||
"type": "string",
|
||||
"title": "Directorio de Vault de Obsidean",
|
||||
"description": "Directorio de Vault de Obsidean",
|
||||
"format": "directory",
|
||||
"default": "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM"
|
||||
},
|
||||
"ObsideanProjectsBase": {
|
||||
"type": "string",
|
||||
"title": "Subdirectorio",
|
||||
"description": "Subdirectorio de los proyectos actuales en el Vault de Obsidean",
|
||||
"default": "\\04-SIDEL"
|
||||
},
|
||||
"siemens_exp_directory": {
|
||||
"type": "string",
|
||||
"title": "Directorio base donde esta la exportación de el proyecto de Tia",
|
||||
|
@ -19,18 +32,12 @@
|
|||
"description": "",
|
||||
"format": "directory"
|
||||
},
|
||||
"ObsideanDir": {
|
||||
"io_excel_file_from_ediagram": {
|
||||
"type": "string",
|
||||
"title": "Directorio de Vault de Obsidean",
|
||||
"description": "Directorio de Vault de Obsidean",
|
||||
"format": "directory",
|
||||
"default": "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM"
|
||||
},
|
||||
"ObsideanProjectsBase": {
|
||||
"type": "string",
|
||||
"title": "Subdirectorio",
|
||||
"description": "Subdirectorio de los proyectos actuales en el Vault de Obsidean",
|
||||
"default": "\\04-SIDEL"
|
||||
"title": "IO scanned from ED",
|
||||
"description": "IO scanned from Electrica Diagram",
|
||||
"format": "file",
|
||||
"default": "IO.xlsx"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -396,6 +396,18 @@ function generateInputField(def, key, value, level) {
|
|||
</button>
|
||||
</div>`;
|
||||
}
|
||||
if (def.format === 'file') {
|
||||
return `<div class="flex gap-2">
|
||||
<input type="text" value="${value || ''}"
|
||||
class="${baseClasses} flex-grow" data-key="${key}">
|
||||
<button type="button"
|
||||
onclick="browseFieldFile(this)"
|
||||
class="bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600"
|
||||
data-key="${key}">
|
||||
Buscar...
|
||||
</button>
|
||||
</div>`;
|
||||
}
|
||||
if (def.enum) {
|
||||
return `<select class="${baseClasses}" data-key="${key}">
|
||||
${def.enum.map(opt => `<option value="${opt}" ${value === opt ? 'selected' : ''}>${opt}</option>`).join('')}
|
||||
|
@ -439,6 +451,29 @@ async function browseFieldDirectory(button) {
|
|||
}
|
||||
}
|
||||
|
||||
// Agregar nueva función para manejar la búsqueda de un archivo
|
||||
async function browseFieldFile(button) {
|
||||
const input = button.parentElement.querySelector('input');
|
||||
const currentPath = input.value;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/browse-files?current_path=${encodeURIComponent(currentPath)}`);
|
||||
const result = await response.json();
|
||||
|
||||
if (result.status === 'success') {
|
||||
input.value = result.path;
|
||||
// Disparar un evento change para actualizar el valor internamente
|
||||
const event = new Event('change', {
|
||||
bubbles: true
|
||||
});
|
||||
input.dispatchEvent(event);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error browsing file:', error);
|
||||
alert('Error al buscar el archivo');
|
||||
}
|
||||
}
|
||||
|
||||
async function modifySchema(level) {
|
||||
try {
|
||||
console.log('Loading schema for level:', level); // Debug line
|
||||
|
@ -546,6 +581,7 @@ function createFieldEditor(key, field) {
|
|||
onchange="updateFieldType(this)">
|
||||
<option value="string" ${field.type === 'string' && !field.enum && !field.format ? 'selected' : ''}>Texto</option>
|
||||
<option value="directory" ${field.type === 'string' && field.format === 'directory' ? 'selected' : ''}>Directorio</option>
|
||||
<option value="file" ${field.type === 'string' && field.format === 'file' ? 'selected' : ''}>Archivo</option>
|
||||
<option value="number" ${field.type === 'number' ? 'selected' : ''}>Número</option>
|
||||
<option value="boolean" ${field.type === 'boolean' ? 'selected' : ''}>Booleano</option>
|
||||
<option value="enum" ${field.enum ? 'selected' : ''}>Lista de Opciones</option>
|
||||
|
@ -652,16 +688,19 @@ function updateVisualSchema() {
|
|||
const defaultValueString = defaultValueInput.value;
|
||||
|
||||
let propertyDefinition = {
|
||||
type: fieldType === 'directory' || fieldType === 'enum' ? 'string' : fieldType, // El tipo base
|
||||
type: fieldType === 'directory' || fieldType === 'enum' || fieldType === 'file' ? 'string' : fieldType, // El tipo base
|
||||
title: title,
|
||||
description: description
|
||||
};
|
||||
|
||||
// Añadir formato específico si es directorio
|
||||
// Añadir formato específico si es directorio o archivo
|
||||
if (select.value === 'directory') {
|
||||
propertyDefinition.format = 'directory';
|
||||
} else if (select.value === 'file') {
|
||||
propertyDefinition.format = 'file';
|
||||
}
|
||||
|
||||
|
||||
// Añadir enum si es de tipo enum
|
||||
if (select.value === 'enum') {
|
||||
propertyDefinition.enum = field.querySelector('textarea').value.split('\n').filter(v => v.trim());
|
||||
|
|
Loading…
Reference in New Issue