diff --git a/.doc/backend_setup.md b/.doc/backend_setup.md
index f05cb45..b786cda 100644
--- a/.doc/backend_setup.md
+++ b/.doc/backend_setup.md
@@ -54,7 +54,7 @@ def main():
scl_output_dir = level2_config.get("scl_output_dir", "scl_output")
xref_output_dir = level2_config.get("xref_output_dir", "xref_output")
- print(f"Directorio de trabajo: {working_directory}")
+ print(f"Directorio de salida/resultados: {working_directory}")
print(f"Directorio de salida SCL: {scl_output_dir}")
if __name__ == "__main__":
@@ -65,10 +65,18 @@ if __name__ == "__main__":
Este archivo contiene los parámetros de tu script. La estructura interna del JSON, como el uso de `"level1"`, `"level2"`, etc., es una convención para organizar los parámetros. `load_configuration()` simplemente lee el archivo y devuelve su contenido.
+### Tipos de Configuración
+
+El sistema distingue entre dos tipos principales de configuración:
+
+1. **`working_directory`**: Es el directorio donde el script guardará sus archivos de salida y resultados. En la interfaz web aparece como "Directorio de Resultados".
+
+2. **`level3`**: Contiene los datos de entrada que el script necesita para procesar. En la interfaz web aparece como "Datos de Ingreso". Estos pueden incluir rutas de archivos de entrada, parámetros específicos de procesamiento, etc.
+
**Ejemplo de `script_config.json`:**
```json
{
- "working_directory": "/ruta/al/directorio/de/trabajo",
+ "working_directory": "/ruta/al/directorio/de/salida/resultados",
"level1": {
"parametro_global_1": "valor1"
},
@@ -77,6 +85,7 @@ Este archivo contiene los parámetros de tu script. La estructura interna del JS
"xref_output_dir": "xref_output"
},
"level3": {
+ "archivo_entrada": "datos.xlsx",
"parametro_especifico_1": true
}
}
@@ -110,9 +119,9 @@ Contienen los datos y variables que utilizará el script. La configuración se s
- **Utilidad:** Define parámetros compartidos por todos los scripts de un grupo.
- **Acceso:** Sus datos se cargan en la clave `"level2"`.
-- **`work_dir.json` (Nivel 3 - Directorio de Trabajo)**
+- **`work_dir.json` (Nivel 3 - Datos de Ingreso)**
- **Ubicación:** Dentro del directorio de trabajo que el script va a procesar.
- - **Utilidad:** Contiene parámetros para una ejecución específica. Es el nivel más específico y sobrescribe los anteriores.
+ - **Utilidad:** Contiene los datos de entrada que el script necesita para procesar. Es el nivel más específico y sobrescribe los anteriores.
- **Acceso:** Sus datos se cargan en la clave `"level3"`.
### Archivos de Esquema (Definiciones de Estructura)
diff --git a/app.py b/app.py
index d6ec9b0..e0862ec 100644
--- a/app.py
+++ b/app.py
@@ -497,6 +497,103 @@ def open_miniconda_console():
)
+@app.route("/api/update-backend-setup", methods=["POST"])
+def update_backend_setup():
+ """Actualizar todos los archivos backend_setup.md copiando desde el archivo principal"""
+ try:
+ # Ruta del archivo fuente (el archivo principal)
+ source_file = r"D:\Proyectos\Scripts\ParamManagerScripts\.doc\backend_setup.md"
+
+ # Verificar que el archivo fuente existe
+ if not os.path.isfile(source_file):
+ return (
+ jsonify(
+ {
+ "status": "error",
+ "message": f"Archivo fuente no encontrado: {source_file}",
+ }
+ ),
+ 404,
+ )
+
+ # Directorio base donde buscar
+ base_dir = r"D:\Proyectos\Scripts"
+
+ # Contadores para el reporte
+ total_files = 0
+ updated_files = 0
+ errors = []
+
+ # Leer el contenido del archivo fuente
+ try:
+ with open(source_file, "r", encoding="utf-8") as f:
+ source_content = f.read()
+ except Exception as e:
+ return (
+ jsonify(
+ {
+ "status": "error",
+ "message": f"Error leyendo archivo fuente: {str(e)}",
+ }
+ ),
+ 500,
+ )
+
+ # Buscar todos los archivos backend_setup.md en subdirectorios .doc
+ for root, dirs, files in os.walk(base_dir):
+ # Solo procesar si estamos en un directorio .doc
+ if os.path.basename(root) == ".doc":
+ for file in files:
+ if file == "backend_setup.md":
+ total_files += 1
+ target_file = os.path.join(root, file)
+
+ # Saltar el archivo fuente para evitar auto-copia
+ if os.path.abspath(target_file) == os.path.abspath(source_file):
+ continue
+
+ try:
+ # Copiar el contenido
+ with open(target_file, "w", encoding="utf-8") as f:
+ f.write(source_content)
+ updated_files += 1
+ print(f"✅ Actualizado: {target_file}")
+ except Exception as e:
+ error_msg = f"Error actualizando {target_file}: {str(e)}"
+ errors.append(error_msg)
+ print(f"❌ {error_msg}")
+
+ # Preparar mensaje de resultado
+ if updated_files == 0:
+ message = "No se encontraron archivos backend_setup.md para actualizar"
+ else:
+ message = f"Actualizados {updated_files} de {total_files} archivos backend_setup.md"
+ if errors:
+ message += f" ({len(errors)} errores)"
+
+ # Log del resultado
+ broadcast_message(f"🔄 {message}")
+ if errors:
+ for error in errors:
+ broadcast_message(f"❌ {error}")
+
+ return jsonify(
+ {
+ "status": "success",
+ "message": message,
+ "total_files": total_files,
+ "updated_files": updated_files,
+ "errors": errors,
+ }
+ )
+
+ except Exception as e:
+ error_msg = f"Error en update_backend_setup: {str(e)}"
+ print(error_msg)
+ broadcast_message(f"❌ {error_msg}")
+ return jsonify({"status": "error", "message": error_msg}), 500
+
+
@app.route("/api/open-explorer", methods=["POST"])
def open_explorer_route():
data = request.json
@@ -644,6 +741,13 @@ def exit_application(icon, item):
tray_icon.stop()
+# Nuevo: opción del menú de la bandeja para cerrar el servidor
+def shutdown_from_tray(icon, item):
+ """Cerrar el servidor y la aplicación desde el icono de la bandeja."""
+ print("Shutdown requested via tray menu.")
+ shutdown_flask_server()
+
+
# === LAUNCHER GUI APIs ===
@@ -1958,13 +2062,12 @@ if __name__ == "__main__":
flask_thread.start()
# --- Setup and run the system tray icon ---
- icon_path = (
- r"d:\Proyectos\Scripts\ParamManagerScripts\icon.png" # Use absolute path
- )
+ icon_path = os.path.join(app.root_path, "static", "icon.png")
try:
image = Image.open(icon_path)
menu = pystray.Menu(
pystray.MenuItem("Abrir ParamManager", open_app_browser, default=True),
+ pystray.MenuItem("Cerrar servidor", shutdown_from_tray),
pystray.MenuItem("Salir", exit_application),
)
tray_icon = pystray.Icon("ParamManager", image, "ParamManager", menu)
diff --git a/backend/script_groups/EmailCrono/.doc/backend_setup.md b/backend/script_groups/EmailCrono/.doc/backend_setup.md
index f05cb45..b786cda 100644
--- a/backend/script_groups/EmailCrono/.doc/backend_setup.md
+++ b/backend/script_groups/EmailCrono/.doc/backend_setup.md
@@ -54,7 +54,7 @@ def main():
scl_output_dir = level2_config.get("scl_output_dir", "scl_output")
xref_output_dir = level2_config.get("xref_output_dir", "xref_output")
- print(f"Directorio de trabajo: {working_directory}")
+ print(f"Directorio de salida/resultados: {working_directory}")
print(f"Directorio de salida SCL: {scl_output_dir}")
if __name__ == "__main__":
@@ -65,10 +65,18 @@ if __name__ == "__main__":
Este archivo contiene los parámetros de tu script. La estructura interna del JSON, como el uso de `"level1"`, `"level2"`, etc., es una convención para organizar los parámetros. `load_configuration()` simplemente lee el archivo y devuelve su contenido.
+### Tipos de Configuración
+
+El sistema distingue entre dos tipos principales de configuración:
+
+1. **`working_directory`**: Es el directorio donde el script guardará sus archivos de salida y resultados. En la interfaz web aparece como "Directorio de Resultados".
+
+2. **`level3`**: Contiene los datos de entrada que el script necesita para procesar. En la interfaz web aparece como "Datos de Ingreso". Estos pueden incluir rutas de archivos de entrada, parámetros específicos de procesamiento, etc.
+
**Ejemplo de `script_config.json`:**
```json
{
- "working_directory": "/ruta/al/directorio/de/trabajo",
+ "working_directory": "/ruta/al/directorio/de/salida/resultados",
"level1": {
"parametro_global_1": "valor1"
},
@@ -77,6 +85,7 @@ Este archivo contiene los parámetros de tu script. La estructura interna del JS
"xref_output_dir": "xref_output"
},
"level3": {
+ "archivo_entrada": "datos.xlsx",
"parametro_especifico_1": true
}
}
@@ -110,9 +119,9 @@ Contienen los datos y variables que utilizará el script. La configuración se s
- **Utilidad:** Define parámetros compartidos por todos los scripts de un grupo.
- **Acceso:** Sus datos se cargan en la clave `"level2"`.
-- **`work_dir.json` (Nivel 3 - Directorio de Trabajo)**
+- **`work_dir.json` (Nivel 3 - Datos de Ingreso)**
- **Ubicación:** Dentro del directorio de trabajo que el script va a procesar.
- - **Utilidad:** Contiene parámetros para una ejecución específica. Es el nivel más específico y sobrescribe los anteriores.
+ - **Utilidad:** Contiene los datos de entrada que el script necesita para procesar. Es el nivel más específico y sobrescribe los anteriores.
- **Acceso:** Sus datos se cargan en la clave `"level3"`.
### Archivos de Esquema (Definiciones de Estructura)
diff --git a/backend/script_groups/EmailCrono/work_dir.json b/backend/script_groups/EmailCrono/work_dir.json
index 85a606e..cb42166 100644
--- a/backend/script_groups/EmailCrono/work_dir.json
+++ b/backend/script_groups/EmailCrono/work_dir.json
@@ -1,15 +1,6 @@
{
"path": "D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\Entregado por VM\\01 - 26-07-2025 Max - Emails",
"history": [
- "D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\Entregado por VM\\01 - 26-07-2025 Max - Emails",
- "C:\\Users\\migue\\OneDrive\\Miguel\\Obsidean\\Trabajo\\VM\\03-VM\\45 - HENKEL - VM Auto Changeover",
- "C:\\Trabajo\\SIDEL\\14 - E5.007172 - Modifica O&U - SAE340\\Reporte\\Email",
- "C:\\Trabajo\\SIDEL\\12 - SAE052 - Syrup Update & GSD Update\\Reporte\\Emails",
- "C:\\Trabajo\\SIDEL\\10 - E5.007095 - Modifica O&U - SAE463\\Reporte\\Email",
- "C:\\Trabajo\\SIDEL\\08 - Masselli TEST\\Reporte\\EMAILs",
- "C:\\Trabajo\\SIDEL\\EMAILs\\I_ E5.007727 _ Evo On - SFSRFH300172 + SFSRFH300109 - ANDIA LACTEOS",
- "C:\\Estudio",
- "C:\\Trabajo\\VM\\40 - 93040 - HENKEL - NEXT2 Problem\\Reporte\\EmailTody",
- "C:\\Trabajo\\VM\\30 - 9.3941- Kosme - Portogallo (Modifica + Linea)\\Reporte\\Emails"
+ "D:\\Trabajo\\VM\\45 - HENKEL - VM Auto Changeover\\Entregado por VM\\01 - 26-07-2025 Max - Emails"
]
}
\ No newline at end of file
diff --git a/backend/script_groups/IO_adaptation/.doc/backend_setup.md b/backend/script_groups/IO_adaptation/.doc/backend_setup.md
index f05cb45..b786cda 100644
--- a/backend/script_groups/IO_adaptation/.doc/backend_setup.md
+++ b/backend/script_groups/IO_adaptation/.doc/backend_setup.md
@@ -54,7 +54,7 @@ def main():
scl_output_dir = level2_config.get("scl_output_dir", "scl_output")
xref_output_dir = level2_config.get("xref_output_dir", "xref_output")
- print(f"Directorio de trabajo: {working_directory}")
+ print(f"Directorio de salida/resultados: {working_directory}")
print(f"Directorio de salida SCL: {scl_output_dir}")
if __name__ == "__main__":
@@ -65,10 +65,18 @@ if __name__ == "__main__":
Este archivo contiene los parámetros de tu script. La estructura interna del JSON, como el uso de `"level1"`, `"level2"`, etc., es una convención para organizar los parámetros. `load_configuration()` simplemente lee el archivo y devuelve su contenido.
+### Tipos de Configuración
+
+El sistema distingue entre dos tipos principales de configuración:
+
+1. **`working_directory`**: Es el directorio donde el script guardará sus archivos de salida y resultados. En la interfaz web aparece como "Directorio de Resultados".
+
+2. **`level3`**: Contiene los datos de entrada que el script necesita para procesar. En la interfaz web aparece como "Datos de Ingreso". Estos pueden incluir rutas de archivos de entrada, parámetros específicos de procesamiento, etc.
+
**Ejemplo de `script_config.json`:**
```json
{
- "working_directory": "/ruta/al/directorio/de/trabajo",
+ "working_directory": "/ruta/al/directorio/de/salida/resultados",
"level1": {
"parametro_global_1": "valor1"
},
@@ -77,6 +85,7 @@ Este archivo contiene los parámetros de tu script. La estructura interna del JS
"xref_output_dir": "xref_output"
},
"level3": {
+ "archivo_entrada": "datos.xlsx",
"parametro_especifico_1": true
}
}
@@ -110,9 +119,9 @@ Contienen los datos y variables que utilizará el script. La configuración se s
- **Utilidad:** Define parámetros compartidos por todos los scripts de un grupo.
- **Acceso:** Sus datos se cargan en la clave `"level2"`.
-- **`work_dir.json` (Nivel 3 - Directorio de Trabajo)**
+- **`work_dir.json` (Nivel 3 - Datos de Ingreso)**
- **Ubicación:** Dentro del directorio de trabajo que el script va a procesar.
- - **Utilidad:** Contiene parámetros para una ejecución específica. Es el nivel más específico y sobrescribe los anteriores.
+ - **Utilidad:** Contiene los datos de entrada que el script necesita para procesar. Es el nivel más específico y sobrescribe los anteriores.
- **Acceso:** Sus datos se cargan en la clave `"level3"`.
### Archivos de Esquema (Definiciones de Estructura)
diff --git a/backend/script_groups/TwinCat/.doc/backend_setup.md b/backend/script_groups/TwinCat/.doc/backend_setup.md
index f05cb45..b786cda 100644
--- a/backend/script_groups/TwinCat/.doc/backend_setup.md
+++ b/backend/script_groups/TwinCat/.doc/backend_setup.md
@@ -54,7 +54,7 @@ def main():
scl_output_dir = level2_config.get("scl_output_dir", "scl_output")
xref_output_dir = level2_config.get("xref_output_dir", "xref_output")
- print(f"Directorio de trabajo: {working_directory}")
+ print(f"Directorio de salida/resultados: {working_directory}")
print(f"Directorio de salida SCL: {scl_output_dir}")
if __name__ == "__main__":
@@ -65,10 +65,18 @@ if __name__ == "__main__":
Este archivo contiene los parámetros de tu script. La estructura interna del JSON, como el uso de `"level1"`, `"level2"`, etc., es una convención para organizar los parámetros. `load_configuration()` simplemente lee el archivo y devuelve su contenido.
+### Tipos de Configuración
+
+El sistema distingue entre dos tipos principales de configuración:
+
+1. **`working_directory`**: Es el directorio donde el script guardará sus archivos de salida y resultados. En la interfaz web aparece como "Directorio de Resultados".
+
+2. **`level3`**: Contiene los datos de entrada que el script necesita para procesar. En la interfaz web aparece como "Datos de Ingreso". Estos pueden incluir rutas de archivos de entrada, parámetros específicos de procesamiento, etc.
+
**Ejemplo de `script_config.json`:**
```json
{
- "working_directory": "/ruta/al/directorio/de/trabajo",
+ "working_directory": "/ruta/al/directorio/de/salida/resultados",
"level1": {
"parametro_global_1": "valor1"
},
@@ -77,6 +85,7 @@ Este archivo contiene los parámetros de tu script. La estructura interna del JS
"xref_output_dir": "xref_output"
},
"level3": {
+ "archivo_entrada": "datos.xlsx",
"parametro_especifico_1": true
}
}
@@ -110,9 +119,9 @@ Contienen los datos y variables que utilizará el script. La configuración se s
- **Utilidad:** Define parámetros compartidos por todos los scripts de un grupo.
- **Acceso:** Sus datos se cargan en la clave `"level2"`.
-- **`work_dir.json` (Nivel 3 - Directorio de Trabajo)**
+- **`work_dir.json` (Nivel 3 - Datos de Ingreso)**
- **Ubicación:** Dentro del directorio de trabajo que el script va a procesar.
- - **Utilidad:** Contiene parámetros para una ejecución específica. Es el nivel más específico y sobrescribe los anteriores.
+ - **Utilidad:** Contiene los datos de entrada que el script necesita para procesar. Es el nivel más específico y sobrescribe los anteriores.
- **Acceso:** Sus datos se cargan en la clave `"level3"`.
### Archivos de Esquema (Definiciones de Estructura)
diff --git a/data/log.txt b/data/log.txt
index 5ef90ad..38f77d4 100644
--- a/data/log.txt
+++ b/data/log.txt
@@ -1,26 +1 @@
-[11:30:11] Iniciando ejecución de manager.py en D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\OllamaTools\out...
-[11:30:11] ⚠️ No se pudo importar load_configuration, usando configuración por defecto
-[11:30:11] 🦙 Ollama Model Manager - Iniciando...
-[11:30:11] 🌐 Servidor iniciado en: http://127.0.0.1:51942
-[11:30:11] 🦙 Ollama Host: http://localhost:11434
-[11:30:11] 📋 Funcionalidades disponibles:
-[11:30:11] - Listar modelos instalados
-[11:30:11] - Ver información detallada de modelos
-[11:30:11] - Descargar nuevos modelos
-[11:30:11] - Eliminar modelos existentes
-[11:30:11] - Monitoreo de espacio ocupado
-[11:30:11] ⏹️ Presiona Ctrl+C para cerrar el servidor
-[11:30:11] * Serving Flask app 'manager'
-[11:30:11] * Debug mode: off
-[11:30:13] 🌐 Navegador abierto en: http://127.0.0.1:51942
-[16:29:51] Ejecutando script GUI: main.py
-[16:29:51] Entorno Python: tia_scripting
-[16:29:51] Ejecutable: pythonw.exe (sin logging)
-[16:29:51] Comando: C:\Users\migue\miniconda3\envs\tia_scripting\pythonw.exe D:/Proyectos/Scripts/RS485/MaselliSimulatorApp\main.py
-[16:29:51] Directorio: D:/Proyectos/Scripts/RS485/MaselliSimulatorApp
-[16:29:51] Encoding: UTF-8 (PYTHONUTF8=1, PYTHONIOENCODING=utf-8)
-[16:29:51] ==================================================
-[16:29:51] Script GUI ejecutado sin logging (pythonw.exe)
-[16:29:51] PID: 22124
-[16:29:51] ==================================================
-[16:29:51] ID de ejecución: 23248897
+[11:24:53] 🔄 Actualizados 3 de 4 archivos backend_setup.md
diff --git a/static/js/scripts.js b/static/js/scripts.js
index 6b9519d..4bafb6b 100644
--- a/static/js/scripts.js
+++ b/static/js/scripts.js
@@ -1396,6 +1396,50 @@ function openMinicondaConsole() {
});
}
+function updateBackendSetup(btnEl) {
+ // Mostrar confirmación antes de proceder
+ if (!confirm('¿Estás seguro de que quieres actualizar todos los archivos backend_setup.md?\n\nEsto copiará el contenido del archivo principal a todos los archivos backend_setup.md encontrados en subdirectorios .doc.')) {
+ return;
+ }
+
+ // Mostrar indicador de carga
+ const button = btnEl;
+ const originalText = button ? button.innerHTML : null;
+ if (button) {
+ button.innerHTML = '⏳ Actualizando...';
+ button.disabled = true;
+ }
+
+ fetch('/api/update-backend-setup', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 'success') {
+ showNotification(`✅ ${data.message}`, 'success');
+ if (data.updated_files > 0) {
+ console.log(`Actualizados ${data.updated_files} archivos de ${data.total_files} encontrados`);
+ }
+ } else {
+ showNotification(`❌ Error: ${data.message}`, 'error');
+ }
+ })
+ .catch(error => {
+ console.error('Error updating backend setup:', error);
+ showNotification('Error al comunicarse con el servidor', 'error');
+ })
+ .finally(() => {
+ // Restaurar el botón
+ if (button && originalText !== null) {
+ button.innerHTML = originalText;
+ button.disabled = false;
+ }
+ });
+}
+
async function openCurrentWorkingDirectoryInExplorer() {
const group = currentGroup; // Asumiendo que currentGroup está disponible globalmente
const wdInput = document.getElementById('working-directory');
diff --git a/templates/index.html b/templates/index.html
index c15122f..a114a1e 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -80,6 +80,10 @@
onclick="openMinicondaConsole()">
Abrir Miniconda Console
+