| |
|
| |
|
| | import streamlit as st
|
| |
|
| | from datetime import datetime
|
| |
|
| | from ..database.sql_db import (
|
| | get_user,
|
| | get_student_user,
|
| | get_admin_user,
|
| | get_teacher_user,
|
| | create_student_user,
|
| | update_student_user,
|
| | delete_student_user,
|
| | record_login,
|
| | record_logout,
|
| | get_recent_sessions,
|
| | get_user_total_time
|
| | )
|
| |
|
| | from ..database.morphosintax_mongo_db import get_student_morphosyntax_analysis
|
| |
|
| | from ..auth.auth import hash_password
|
| |
|
| |
|
| | def format_duration(seconds):
|
| | """Convierte segundos a formato legible"""
|
| | if not seconds:
|
| | return "0h 0m"
|
| | hours = seconds // 3600
|
| | minutes = (seconds % 3600) // 60
|
| | return f"{hours}h {minutes}m"
|
| |
|
| | def admin_page():
|
| | st.title("Panel de Administración")
|
| | st.write(f"Bienvenido, {st.session_state.username}")
|
| |
|
| |
|
| | tab1, tab2, tab3 = st.tabs([
|
| | "Gestión de Usuarios",
|
| | "Búsqueda de Usuarios",
|
| | "Actividad de la Plataforma"
|
| | ])
|
| |
|
| |
|
| |
|
| |
|
| | with tab1:
|
| | st.header("Crear Nuevo Usuario Estudiante")
|
| |
|
| |
|
| | col1, col2 = st.columns(2)
|
| |
|
| | with col1:
|
| | new_username = st.text_input(
|
| | "Correo electrónico del nuevo usuario",
|
| | key="admin_new_username"
|
| | )
|
| |
|
| | with col2:
|
| | new_password = st.text_input(
|
| | "Contraseña",
|
| | type="password",
|
| | key="admin_new_password"
|
| | )
|
| |
|
| | if st.button("Crear Usuario", key="admin_create_user", type="primary"):
|
| | if new_username and new_password:
|
| | try:
|
| |
|
| | hashed_password = hash_password(new_password)
|
| | if create_student_user(new_username, hashed_password, {'partitionKey': new_username}):
|
| | st.success(f"Usuario estudiante {new_username} creado exitosamente")
|
| | else:
|
| | st.error("Error al crear el usuario estudiante")
|
| | except Exception as e:
|
| | st.error(f"Error al crear usuario: {str(e)}")
|
| | else:
|
| | st.warning("Por favor complete todos los campos")
|
| |
|
| |
|
| |
|
| | with tab2:
|
| | st.header("Búsqueda de Usuarios")
|
| |
|
| | search_col1, search_col2 = st.columns([2,1])
|
| |
|
| | with search_col1:
|
| | student_username = st.text_input(
|
| | "Nombre de usuario del estudiante",
|
| | key="admin_view_student"
|
| | )
|
| |
|
| | with search_col2:
|
| | search_button = st.button(
|
| | "Buscar",
|
| | key="admin_view_student_data",
|
| | type="primary"
|
| | )
|
| |
|
| | if search_button:
|
| | student = get_student_user(student_username)
|
| | if student:
|
| |
|
| | info_tab1, info_tab2, info_tab3 = st.tabs([
|
| | "Información Básica",
|
| | "Análisis Realizados",
|
| | "Tiempo en Plataforma"
|
| | ])
|
| |
|
| | with info_tab1:
|
| | st.subheader("Información del Usuario")
|
| | st.json(student)
|
| |
|
| | with info_tab2:
|
| | st.subheader("Análisis Realizados")
|
| | student_data = get_student_morphosyntax_analysis(student_username)
|
| | if student_data:
|
| | st.json(student_data)
|
| | else:
|
| | st.info("No hay datos de análisis para este estudiante.")
|
| |
|
| | with info_tab3:
|
| | st.subheader("Tiempo en Plataforma")
|
| | total_time = get_user_total_time(student_username)
|
| | if total_time:
|
| | st.metric(
|
| | "Tiempo Total",
|
| | format_duration(total_time)
|
| | )
|
| | else:
|
| | st.info("No hay registros de tiempo para este usuario")
|
| | else:
|
| | st.error("Estudiante no encontrado")
|
| |
|
| |
|
| |
|
| | with tab3:
|
| | st.header("Actividad Reciente")
|
| |
|
| |
|
| | if st.button("Actualizar datos", key="refresh_sessions", type="primary"):
|
| | st.rerun()
|
| |
|
| |
|
| | with st.spinner("Cargando datos de sesiones..."):
|
| |
|
| | recent_sessions = get_recent_sessions(20)
|
| |
|
| | if recent_sessions:
|
| |
|
| | sessions_data = []
|
| | for session in recent_sessions:
|
| | try:
|
| |
|
| | try:
|
| | login_time = datetime.fromisoformat(
|
| | session['loginTime'].replace('Z', '+00:00')
|
| | ).strftime("%Y-%m-%d %H:%M:%S")
|
| | except Exception as e:
|
| | login_time = session['loginTime']
|
| |
|
| |
|
| | if session.get('logoutTime') and session['logoutTime'] != "Activo":
|
| | try:
|
| | logout_time = datetime.fromisoformat(
|
| | session['logoutTime'].replace('Z', '+00:00')
|
| | ).strftime("%Y-%m-%d %H:%M:%S")
|
| | except Exception as e:
|
| | logout_time = session['logoutTime']
|
| | else:
|
| | logout_time = "Activo"
|
| |
|
| |
|
| | sessions_data.append({
|
| | "Usuario": session.get('username', 'Desconocido'),
|
| | "Inicio de Sesión": login_time,
|
| | "Fin de Sesión": logout_time,
|
| | "Duración": format_duration(session.get('sessionDuration', 0))
|
| | })
|
| | except Exception as e:
|
| | st.error(f"Error procesando sesión: {str(e)}")
|
| | continue
|
| |
|
| |
|
| | with st.expander("Información de depuración", expanded=False):
|
| | st.write("Datos crudos recuperados:")
|
| | st.json(recent_sessions)
|
| |
|
| | st.write("Datos procesados para mostrar:")
|
| | st.json(sessions_data)
|
| |
|
| |
|
| | st.dataframe(
|
| | sessions_data,
|
| | hide_index=True,
|
| | column_config={
|
| | "Usuario": st.column_config.TextColumn(
|
| | "Usuario",
|
| | width="medium"
|
| | ),
|
| | "Inicio de Sesión": st.column_config.TextColumn(
|
| | "Inicio de Sesión",
|
| | width="medium"
|
| | ),
|
| | "Fin de Sesión": st.column_config.TextColumn(
|
| | "Fin de Sesión",
|
| | width="medium"
|
| | ),
|
| | "Duración": st.column_config.TextColumn(
|
| | "Duración",
|
| | width="small"
|
| | )
|
| | }
|
| | )
|
| |
|
| |
|
| | total_sessions = len(sessions_data)
|
| | total_users = len(set(session['Usuario'] for session in sessions_data))
|
| |
|
| | metric_col1, metric_col2 = st.columns(2)
|
| | with metric_col1:
|
| | st.metric("Total de Sesiones", total_sessions)
|
| | with metric_col2:
|
| | st.metric("Usuarios Únicos", total_users)
|
| | else:
|
| | st.info("No hay registros de sesiones recientes o hubo un problema al recuperarlos.")
|
| |
|
| |
|
| | if st.button("Mostrar diagnóstico"):
|
| | st.write("Verificando la función get_recent_sessions:")
|
| | container = get_container("users_sessions")
|
| | if container:
|
| | st.success("✅ Conectado al contenedor users_sessions")
|
| | else:
|
| | st.error("❌ No se pudo conectar al contenedor users_sessions")
|
| |
|
| |
|
| |
|
| |
|
| | st.markdown("---")
|
| |
|
| |
|
| |
|
| | col1, col2, col3 = st.columns([2,1,2])
|
| | with col2:
|
| | if st.button("Cerrar Sesión", key="admin_logout", type="primary", use_container_width=True):
|
| | from ..auth.auth import logout
|
| | logout()
|
| | st.rerun() |