import gradio as gr import networkx as nx import matplotlib.pyplot as plt import uuid import os import json import textwrap import requests import pandas as pd api_key = os.getenv("AIRT_KEY") AIRT_DBASEx = os.getenv("AIRT_DBASE") AIRT_TABLEx = os.getenv("AIRT_TABLE") # Use Directed Graph to represent relationships G = nx.DiGraph() # Fix: Use DiGraph instead of Graph url = f"https://api.airtable.com/v0/{AIRT_DBASEx}/{AIRT_TABLEx}" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } # Cargar el JSON de normativas def cargar_normativas(): with open('normativas.json', 'r', encoding='utf-8') as f: return json.load(f) # Cargar la lista de estudiantes def cargar_estudiantes(): with open('estudiantes.json', 'r', encoding='utf-8') as f: return json.load(f) def crear_html(normativa): htmlx = f"""

{normativa["nombre"]}

{normativa["titulo"], normativa["año"]}

ID: {normativa["id"]}

Descripción: {normativa["descripcion"]}

Enfoque de Gestión: {normativa["enfoque_riesgo"]}

Opinión Docente: {normativa["opinion_docente"]}

Visite este sitio web para más información.

""" return htmlx def mostrar_detalles(normativa_seleccionada): if not normativa_seleccionada: return "

Por favor selecciona una normativa

", None normativas = cargar_normativas() partes = normativa_seleccionada.split() id_normativa = normativa['nombre'] for normativa in normativas["normativa_peruana_gestion_riesgos"]: if id_normativa == normativa['nombre']: html = crear_html(normativa) return html def mostrar_detalles(normativa_seleccionada): if not normativa_seleccionada: return "

Por favor selecciona una normativa

", "" normativas = cargar_normativas() id_normativa = normativa_seleccionada # Extract the norm name for normativa in normativas["normativa_peruana_gestion_riesgos"]: if id_normativa == normativa['nombre']: return crear_html(normativa), normativa["nombre"] # Return both HTML and name return "

No se encontró la normativa

", "" def cargar_desde_airtable(): response = requests.get(url, headers=headers) if response.status_code != 200: print(f"Error: {response.status_code} - {response.text}") # Debugging info return pd.DataFrame(columns=["Nombre", "Enfoque", "Norma", "Texto_HF"]) # Return empty DataFrame records = response.json().get("records", []) # Compact list comprehension to extract data aportes = [ [record["fields"].get("Nombre", ""), record["fields"].get("Enfoque", ""), record["fields"].get("Norma", ""), record["fields"].get("Texto_HF", "")] for record in records ] return pd.DataFrame(aportes, columns=["Nombre", "Enfoque", "Norma", "Texto_HF"]) def wrap_text(text, width=10): return "\n".join(textwrap.wrap(text, width=width)) def inicializar_grafo(): df = cargar_desde_airtable() # Add base nodes for categories G.add_node("Determinista", color='red') G.add_node("Sistémico", color='blue') # Process each row and add nodes/edges for _, row in df.iterrows(): nombre, enfoque, norma, texto = row["Nombre"], row["Enfoque"], row["Norma"], row["Texto_HF"] textox = wrap_text(f"{nombre}: {texto}") if not G.has_node(norma): G.add_node(norma, color='gray') if not G.has_edge(norma, enfoque): G.add_edge(norma, enfoque, label=textox) def guardar_en_airtable(nombre, enfoque, norma, texto): data = {"fields": {"Nombre": nombre, "Enfoque": enfoque, "Norma": norma, "Texto_HF": texto}} requests.post(url, headers=headers, json=data) def agregar_aporte(nombre, enfoque, norma, texto): textox = wrap_text(f"{nombre}: {texto}") if not G.has_node(norma): G.add_node(norma, color='gray') if not G.has_edge(norma, enfoque): G.add_edge(norma, enfoque, label=textox) guardar_en_airtable(nombre, enfoque, norma, texto) return visualizar_grafo() def visualizar_grafo(): plt.figure(figsize=(8, 8)) pos = nx.spring_layout(G) edge_labels = nx.get_edge_attributes(G, 'label') nx.draw(G, pos, with_labels=True, node_color='lightblue', edge_color='gray', node_size=2000, font_size=10) nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=8) plt.title("Red de Aportes") plt.savefig("graph.png") plt.close() return "graph.png" inicializar_grafo() normativas = cargar_normativas() estudiantes = cargar_estudiantes() norm_options = [f"{norm['nombre']} {norm['id']}" for norm in normativas["normativa_peruana_gestion_riesgos"]] student_names = [student for student in estudiantes["estudiantes"]] iface = gr.Blocks() with iface: gr.Markdown("# Foro Dinámico con Visualización de Red") with gr.Row(): gr.Markdown('## Selección de Norma') normativa_dropdown.change(fn=mostrar_detalles, inputs=normativa_dropdown, outputs=[normativa_html, norma_field]) with gr.Row(): gr.Markdown("## Red de Aportes:") graph_output = gr.Image(visualizar_grafo(), label="Red de Aportes") with gr.Row(): nombre = gr.Dropdown(choices=student_names, label="Nombre del Estudiante") enfoque = gr.Radio(["Determinista", "Sistémico"], label="Enfoque") with gr.Row(): norma_field = gr.Textbox(label="Norma", interactive=False) # Read-only texto = gr.Textbox(label="Tu aporte") submit_button = gr.Button("Agregar Aporte") submit_button.click(fn=agregar_aporte, inputs=[nombre, enfoque, norma_field, texto], outputs=graph_output) iface.launch(share=True)