Se añadió una nueva ruta API `/api/update-backend-setup` para actualizar todos los archivos `backend_setup.md` en subdirectorios `.doc` copiando el contenido desde un archivo fuente. Se implementó la lógica para manejar errores y reportar el estado de la actualización. Además, se incorporó un botón en la interfaz de usuario para facilitar esta acción. Se realizaron mejoras en la documentación de `backend_setup.md` y se ajustaron los mensajes de salida para mayor claridad.

This commit is contained in:
Miguel 2025-08-08 11:25:52 +02:00
parent 784f7c59e2
commit 1fda6e656d
9 changed files with 208 additions and 55 deletions

View File

@ -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)

109
app.py
View File

@ -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)

View File

@ -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)

View File

@ -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"
]
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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');

View File

@ -80,6 +80,10 @@
onclick="openMinicondaConsole()">
Abrir Miniconda Console
</button>
<button class="w-full bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded shadow mb-2"
onclick="updateBackendSetup(this)">
🔄 Actualizar backend_setup.md
</button>
<button class="w-full bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded shadow"
onclick="shutdownServer()">
Detener Servidor