feat: fixing certificate and block

This commit is contained in:
2026-04-14 13:07:45 -04:00
parent e0e6655b91
commit 169a0a18a2
21 changed files with 837 additions and 1226 deletions
+1
View File
@@ -53,6 +53,7 @@ WHISPER_MODEL=whisper-large-v3
# External Database Integration (SAM)
# ----------------------------------------
MYSQL_DATABASE_URL=mysql://db_user:db_password@host:3306/database_name
SAM_DIAGNOSTICO_DATABASE_URL=mysql://db_user:db_password@host:3306/SAM_diagnostico
EXTERNAL_TABLE_GRADES=notas
EXTERNAL_ID_TIPO_NOTA=1
-34
View File
@@ -1,34 +0,0 @@
{
"permissions": {
"allow": [
"Bash(rm *)",
"Bash(sed *)",
"Bash(ls *)",
"Bash(true)",
"Bash(cargo check *)",
"Bash(cargo build *)",
"Bash(chmod *)",
"Bash(mkdir *)",
"Bash(ssh *)",
"Bash(git fetch *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git push *)",
"Bash(scp *)",
"Bash(curl *)",
"Bash(sudo *)",
"Bash(grep *)",
"Bash(python3)",
"Bash(with)",
"Bash(as *)",
"Bash(content *)",
"Bash(old_text *)",
"Bash(new_text *)",
"Bash(old_text, *)",
"Bash(f.write)",
"Bash(print)",
"Bash(eof)"
]
},
"$version": 3
}
+89 -705
View File
@@ -2,752 +2,136 @@
OpenCCB es una infraestructura de código abierto para plataformas de gestión de aprendizaje y contenido (LMS/CMS), construida con rendimiento, seguridad y escalabilidad en mente.
---
## 📖 Tabla de Contenidos
- [🚀 Arquitectura Consolidada](#-arquitectura-consolidada)
- [✨ Funcionalidades Destacadas](#-funcionalidades-destacadas)
- [🛠 Stack Tecnológico](#-stack-tecnológico)
- [ requisitos-del-sistema](#requisitos-del-sistema)
- [📦 Guía de Inicio Rápido](#-guía-de-inicio-rápido)
- [📊 Estado de Funcionalidades](#-estado-de-funcionalidades)
- [🔌 Recursos para Desarrolladores](#-recursos-para-desarrolladores)
- [📈 Roadmap](#-roadmap)
---
## 🚀 Arquitectura Consolidada
El proyecto ha sido optimizado para reducir la complejidad de la infraestructura, consolidando los servicios de backend con sus respectivos frontends en contenedores unificados:
El proyecto optimiza la complejidad de infraestructura consolidando servicios de backend en Rust con frontends modernos en Next.js:
1. **Studio + CMS (Puerto 3000/3001)**:
- **Frontend**: Next.js app para administración y creación de contenido.
- **Backend**: API de Rust para gestión (CMS).
2. **Experience + LMS (Puerto 3003/3002)**:
- **Frontend**: Next.js app para la experiencia del estudiante.
- **Backend**: API de Rust para entrega de cursos y calificaciones (LMS).
3. **Database**: PostgreSQL compartido.
4. **AI Services**: stack local con Faster-Whisper (Transcripción) y Ollama (Traducción y Resúmenes).
- **AI Course Wizard**: Generación automática de cursos a partir de prompts estructurados.
- **Course Portability**: Importación/Exportación de cursos completos mediante JSON.
- **User Profiles**: Gestión completa de identidad (avatar, bio, preferencias).
- **Engagement Heatmaps**: Visualización de retención segundo a segundo en videos.
- **Smart Notifications**: Recordatorios de fechas límite y alertas in-app.
- **Global i18n**: Interfaz multilingüe (EN, ES, PT) con persistencia por usuario.
- **Document-Based Learning**: Soporte para actividades de lectura (PDF, DOCX, PPTX).
- **AI English Teacher**: Persona especializada para generación de contenidos y tutoría personalizada.
- **AI Audio Evaluation**: Evaluación inteligente de pronunciación y contenido con feedback en lenguaje natural.
- **Custom AI Quizzes**: Generación de quices con contexto pedagógico y tipo de pregunta personalizable (opción múltiple, V/F, etc.).
- **Course Deletion**: Funcionalidad de eliminación de cursos con verificación de permisos y limpieza en cascada.
- **Gamified Activities**: Nuevos tipos de bloques interactivos incluyendo Juegos de Memoria (con generación automática por IA) y Puntos Calientes (Hotspots).
- **Course Marketing & Summary**: Sistema de metadatos estructurados (objetivos, requisitos) y landing pages premium para una mejor presentación de cursos.
- **Global AI Task Dashboard**: Panel unificado de control en consola administrativa para monitorear, reintentar y cancelar tareas de IA en segundo plano (transcripciones, quices, etc).
- **Dynamic API Resolution**: Resolución inteligente de endpoints que permite el acceso desde cualquier dispositivo en la red local (WiFi) sin configuración manual.
- **Responsive UI/UX**: Interfaces optimizadas para dispositivos móviles con menús adaptativos y escalado fluido de componentes.
- **AI Teaching Assistant (RAG)**: Tutor inteligente dentro de cada lección que ayuda a los estudiantes utilizando el contexto de la lección actual y el historial del curso.
- **Persistent Grade Locking**: Bloqueo persistente de lecciones calificadas tras agotar los intentos, con retroalimentación personalizada generada por IA.
- **Color-Coded Progress Navigation**: Sistema visual de seguimiento de progreso mediante colores (Verde: Completado, Amarillo: En Proceso, Rojo: Repetible) tanto a nivel de lección como de módulo.
- **Adaptive Skill Analysis**: Motor de análisis de etiquetas que calcula la maestría de habilidades (Gramática, Vocabulario, etc.) para personalizar las recomendaciones de IA.
- **Efficient Docker Builds**: Imágenes de contenedor optimizadas para desarrollo rápido y despliegue ligero.
- **Unified Authentication Flow**: Flujo de inicio de sesión simplificado para estudiantes e instructores.
- **Course Monetization**: Integración con Mercado Pago para venta de cursos, con inscripciones automáticas y paneles de precios para instructores.
- **Student Notes**: Sistema de anotaciones personales por lección con auto-guardado inteligente (debounced).
- **Interactive Gradebook**: Libro de calificaciones avanzado con filtrado por cohortes, exportación masiva a CSV con desgloses por categoría y pertenencia a cohortes.
- **Bulk Operations**: Herramientas administrativas para inscripción masiva de usuarios vía email y comunicación segmentada.
- **Course Teams**: Soporte para múltiples instructores por curso con roles granulares (Instructor Principal, Instructor, Asistente).
- **Course Preview**: Capacidad de marcar lecciones específicas como previsualizables para usuarios no inscritos (freemium).
- **Student Progress Dashboard**: Visualización avanzada del avance del estudiante con gráficos de actividad diaria y predicción de fecha de finalización basada en el ritmo de aprendizaje.
- **Segmented Announcements**: Sistema de anuncios con capacidad de dirigirse a cohortes específicas y notificaciones filtradas.
- **Content Libraries**: Repositorio centralizado de bloques y lecciones reutilizables entre múltiples cursos.
- **Advanced Grading (Rubrics)**: Sistema de evaluación basado en rúbricas detalladas con indicadores de desempeño por criterio.
- **Learning Sequences**: Gestión de prerrequisitos entre lecciones con cumplimiento forzado en el LMS.
- **LTI 1.3 Tool Provider**: Interoperabilidad completa para lanzar cursos de OpenCCB desde LMS externos (Canvas, Moodle) de manera segura y estandarizada, con soporte para **Deep Linking** (Content Picking).
- **Global Asset Library**: Repositorio centralizado de medios para toda la organización, permitiendo la reutilización de archivos en múltiples cursos con gestión de cuotas e integridad de datos.
- **Predictive Analytics (Dropout Risk)**: Motor de IA que analiza el desempeño, actividad y compromiso social del estudiante para detectar riesgos de abandono de forma proactiva, con alertas accionables para instructores.
- **Live Learning (Videoconference)**: Integración nativa con Jitsi para clases virtuales síncronas, con programación desde Studio y acceso integrado en Experience.
- **Student Portfolio & Badges**: Sistema de reconocimiento con Open Badges y perfiles públicos profesionales para mostrar logros y progreso verificado.
- **Dynamic Mermaid Diagrams**: Generación automática de diagramas (flowcharts, mapas mentales, secuencias) a partir del contenido de cada lección usando IA, con editor visual integrado para instructores.
1. **Studio + CMS (Puertos 3000/3001)**: Next.js app para administración y API de Rust para gestión de contenido.
2. **Experience + LMS (Puertos 3003/3002)**: Next.js app para estudiantes y API de Rust para entrega y calificaciones.
3. **Database**: PostgreSQL 16 compartido con soporte para **PGVector**.
4. **AI Services**: Stack local con Faster-Whisper (Transcripción) y Ollama (Inferencia LLM).
## Requisitos del Sistema
---
OpenCCB es altamente escalable. A continuación se detallan los requisitos recomendados según la carga de usuarios concurrentes:
## ✨ Funcionalidades Destacadas
### 🧠 Inteligencia Artificial Avanzada
- **AI Course Wizard**: Generación instantánea de currículos completos a partir de un prompt.
- **AI Teaching Assistant (RAG)**: Tutor inteligente con memoria histórica y contexto de la lección actual.
- **Evaluación por Audio**: Análisis de pronunciación y feedback en lenguaje natural usando IA.
- **Diagramas Dinámicos**: Generación automática de diagramas Mermaid (mapas mentales, flujos) desde el contenido.
- **Analíticas Predictivas**: Motor que detecta riesgos de abandono escolar antes de que ocurran.
### 🎓 Gestión Académica Premium
- **Library of Content**: Repositorio centralizado de bloques y lecciones reutilizables.
- **Advanced Gradebook**: Libro de calificaciones con rúbricas detalladas y filtrado por cohortes.
- **Learning Sequences**: Gestión de prerrequisitos y rutas de aprendizaje condicionales.
- **LTI 1.3 Provider**: Interoperabilidad completa con Canvas, Moodle y otros LMS estándar.
### 🎮 Experiencia de Aprendizaje
- **Gamificación Integrada**: Sistema de XP, niveles, Badges (Open Badges) y juegos interactivos (Memoria, Hotspots).
- **Engagement Heatmaps**: Visualización para instructores de la retención segundo a segundo en videos.
- **Student Portfolio**: Perfiles públicos profesionales que muestran logros y progreso verificado.
- **Anotaciones Inteligentes**: Sistema de notas personales con auto-guardado por lección.
### 📱 Conectividad y Acceso
- **Dynamic LAN Access**: Resolución automática de IP para acceder desde cualquier dispositivo en la red WiFi.
- **Responsive UI/UX**: Interfaces optimizadas con diseño *Glassmorphism* y navegación móvil fluida.
- **White-Label Branding**: Personalización completa de marca, colores, logos y favicons por organización.
---
## 🛠 Stack Tecnológico
- **Backend**: [Rust](https://www.rust-lang.org/) (axum, sqlx).
- **Frontend**: [Next.js 14+](https://nextjs.org/) (App Router), [Tailwind CSS](https://tailwindcss.com/).
- **Base de Datos**: [PostgreSQL 16](https://www.postgresql.org/) + [pgvector](https://github.com/pgvector/pgvector).
- **IA In-house**: Faster-Whisper, Ollama (Llama 3.2, Nomic-Embed).
---
## 💻 Requisitos del Sistema
| Componente | **Pequeño (100 u.)** | **Mediano (500 u. concurrentes)** | **Grande (1000+ u.)** |
| :--- | :--- | :--- | :--- |
| **CPU** | 4 vCPUs | 8-12 vCPUs (AVX2/AVX-512) | 16-32+ vCPUs |
| **RAM** | 8 GB | 16-32 GB (Recomendado 24GB+) | 64 GB+ |
| **Almacenamiento** | 50 GB SSD | 250 GB+ NVMe (RAID-1) | 1 TB+ NVMe (S3 Backup) |
| **AI (Opcional)** | N/A (Solo CPU) | NVIDIA RTX 3060+ (12GB VRAM) | Multi-GPU (A100/H100) |
| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS / Debian | Cloud Native (K8s / Terraform) |
| **CPU** | 4 vCPUs | 8-12 vCPUs (AVX2+) | 16-32+ vCPUs |
| **RAM** | 8 GB | 16-32 GB | 64 GB+ |
| **GPU (IA)** | Opcional | NVIDIA RTX 3060+ (12GB) | Multi-GPU (A100/H100) |
> [!NOTE]
> Los requisitos de AI son específicos para la función de transcripción local (Whisper). Si se utiliza una API externa, el requisito de GPU desaparece.
> Los requisitos de GPU son específicos para la autogestión de IA local. Si se utilizan APIs externas, estos requisitos disminuyen drásticamente.
## 🛠 Stack Tecnológico
- **Backend**: Rust (Edition 2024), Axum, SQLx.
- **Frontend**: React, Next.js (App Router), Tailwind CSS, Lucide React.
- **Base de Datos**: PostgreSQL 16.
- **Infraestructura**: Docker & Docker Compose.
- **IA Local**:
- **Faster-Whisper**: Transcripción de audio a texto.
- **Ollama**: Traducción inteligente (EN -> ES), resúmenes y generación de cuestionarios.
- **i18n Infrastructure**: Sistema de traducción reactivo para soporte global.
- **Document Management**: Motor de previsualización de documentos PDF nativo.
---
## 📦 Guía de Inicio Rápido
### Requisitos Previos
- Docker y Docker Compose.
- Node.js 18+ (para desarrollo local).
- Rust (para desarrollo local).
- Docker & Docker Compose
- Node.js 18+ & Rust (para desarrollo local)
### Ejecución con Docker (Recomendado)
```bash
docker-compose up --build
```
Esto iniciará todos los servicios:
- **Studio**: [http://localhost:3000](http://localhost:3000)
- **Experience**: [http://localhost:3003](http://localhost:3003)
- **Studio**: http://localhost:3000
- **Experience**: http://localhost:3003
> [!TIP]
> **Acceso desde Móviles**: Gracias a la *Dynamic API Resolution*, puedes acceder desde tu celular conectado al mismo WiFi usando la IP de tu computadora (ej: `http://192.168.1.15:3000`). La interfaz se adaptará automáticamente.
### Desarrollo Local
#### Studio & CMS
### Comandos de Utilidad
```bash
# Iniciar backend CMS
cd services/cms-service
cargo run
# Instalación y configuración automática
./install.sh
# Iniciar frontend Studio
cd web/studio
npm install
npm run dev
```
#### 📦 Portabilidad de Cursos
Gestiona la movilidad de contenidos entre diferentes organizaciones utilizando exportaciones estandarizadas en JSON.
#### GET /courses/{id}/export
Genera un paquete completo del curso, incluyendo módulos, lecciones y configuraciones de calificación.
#### POST /courses/import
Crea un nuevo curso basado en un paquete de exportación proporcionado. El mapeo automático de dependencias asegura la integridad de los datos en la nueva organización.
#### Experience & LMS
```bash
# Iniciar backend LMS
cd services/lms-service
cargo run
# Iniciar frontend Experience
cd web/experience
npm install
npm run dev
```
#### 🧹 Mantenimiento de Base de Datos
Para resetear completamente el entorno de desarrollo y empezar desde cero:
```bash
# Borra las bases de datos openccb_cms/lms y las vuelve a migrar
# Resetear base de datos de desarrollo
./scripts/reset_db.sh
```
## 🔌 Manual del Desarrollador (API)
### 1. Autenticación y Cuentas
Gestión de registro, login y perfiles organizacionales.
#### POST /auth/register
Crea un nuevo usuario vinculado a la organización por defecto.
- **Cuerpo de la Petición ( AuthPayload ):**
```json
{
"email": "string",
"password": "string",
"full_name": "string",
"role": "string (admin | instructor | student)"
}
```
#### SSO (OpenID Connect)
OpenCCB soporta integración con proveedores de identidad (IdP) externos como Google, Okta y Azure AD.
- **Configuración**: Los administradores de la organización pueden configurar sus credenciales OIDC en el panel de configuración de Studio.
- **Autoprovisionamiento**: Los nuevos usuarios se crean automáticamente en la plataforma tras una autenticación exitosa.
#### LTI 1.3 e Interoperabilidad
OpenCCB actúa como un Tool Provider LTI 1.3 moderno, utilizando OIDC y JWKS para máxima seguridad.
- **JWKS Endpoint**: `/lti/jwks` expone las claves públicas para verificación de firmas.
- **Deep Linking**: Permite que instructores seleccionen cursos o lecciones específicas desde el LMS externo mediante una interfaz de Studio embebida.
- **Autoprovisionamiento**: Los usuarios lanzados vía LTI se crean automáticamente con los roles correspondientes.
```bash
# Registrar un nuevo administrador
curl -X POST "http://localhost:3001/auth/register" \
-H "Content-Type: application/json" \
-d '{"email": "admin@empresa.com", "password": "pass", "full_name": "Admin Name"}'
```
---
### 2. Gestión de Contenidos (CMS)
Herramientas para instructores y administradores.
## 🔌 Recursos para Desarrolladores
#### POST /courses
Crea un nuevo curso vinculado a la organización del usuario.
- **Lógica**: El `instructor_id` se asigna automáticamente desde el token JWT.
- **Cuerpo ( CreateCourseRequest ):**
```json
{
"title": "string",
"pacing_mode": "string (self_paced | instructor_led)"
}
```
```bash
# Crear curso básico
curl -X POST "http://localhost:3001/courses" \
-H "Authorization: Bearer $TOKEN" \
-d '{"title": "Curso de Rust", "pacing_mode": "self_paced"}'
```
#### POST /courses/generate
Utiliza IA para generar la estructura completa de un curso basado en un prompt.
- **Lógica de Generación**: Utiliza modelos de lenguaje (LLM) para descomponer un tema complejo en una malla curricular lógica de módulos y lecciones.
- **Cuerpo de la Petición ( GenerateCourseRequest ):**
```json
{
"prompt": "string"
}
```
#### GET /courses/{id}/export
Exporta un curso completo y su contenido a formato JSON para portabilidad.
- **Integridad Portátil**: Empaqueta metadatos, categorías de calificación, módulos y lecciones manteniendo sus relaciones jerárquicas.
- **Respuesta**: Archivo JSON estandarizado para importación.
#### POST /courses/import
Importa un curso a partir de un archivo JSON generado previamente.
- **Mapeo de Dependencias**: Re-mapea automáticamente los IDs de lecciones y módulos para la nueva organización, asegurando que las relaciones y ponderaciones se mantengan intactas.
- **Cuerpo de la Petición ( CourseBundle ):**
```json
{
"title": "string",
"description": "string",
"modules": []
}
```
#### POST /lessons
Agrega contenido multimedia o evaluaciones a un módulo.
- **Configuración Graduable**: Si `is_graded` es true, los puntos sumarán al XP del estudiante en el LMS.
- **Nuevos Tipos Gamificados**:
- `hotspot`: Identificación visual sobre imágenes (ideal para niños).
- `memory-match`: Juego de memoria con pares conceptuales.
- `video-marker`: Preguntas interactivas en timestamps específicos del video.
- **Cuerpo ( CreateLessonRequest ):**
```json
{
"module_id": "uuid",
"title": "string",
"content_type": "string (video | reading | quiz | hotspot | memory-match | document)",
"content_url": "string (opcional)",
"is_graded": "boolean"
}
```
#### POST /assets/upload
Sube un archivo multimedia o documento a la biblioteca global de la organización.
- **Lógica de Reutilización**: Los activos se asocian a la organización y pueden vincularse opcionalmente a un curso específico. El motor de búsqueda permite localizar rápidamente recursos existentes para evitar duplicados.
- **Cuerpo de la Petición ( MultipartForm ):**
- `file`: Archivo binario (PDF, Video, Imagen, Docx).
- **Respuesta ( UploadResponse ):**
```json
{
"id": "uuid",
"url": "string",
"mimetype": "string"
}
```
```bash
# Agregar lección de video
curl -X POST "http://localhost:3001/lessons" \
-H "Authorization: Bearer $TOKEN" \
-d '{"module_id": "...", "title": "Intro", "content_type": "video", "is_graded": false}'
```
---
### 3. Experiencia de Aprendizaje (LMS)
Endpoints para estudiantes y seguimiento de progreso.
#### POST /enroll
Inscribe al usuario en un curso.
- **Lógica**: Verifica que el curso pertenezca a la misma organización que el usuario.
- **Cuerpo ( EnrollPayload ):**
```json
{
"course_id": "uuid"
}
```
```bash
# Inscribirse en un curso
curl -X POST "http://localhost:3002/enroll" \
-H "Authorization: Bearer $TOKEN" \
-d '{"course_id": "uuid-del-curso"}'
```
#### POST /grades
Registra el puntaje de una lección y actualiza la gamificación.
- **Lógica Inteligente**: Actualiza automáticamente el XP del usuario y despacha webhooks si el curso se completa.
- **Engagement Tracking**: Si la lección contiene video, el frontend envía eventos de "heartbeat" cada 5 segundos para generar mapas de calor.
#### GET /notifications
Obtiene las notificaciones pendientes del usuario.
- **Filtro de Relevancia**: Devuelve únicamente alertas no leídas sobre fechas límite próximas o logros de gamificación recientes.
- **Respuesta**: Array de `Notification`.
#### POST /notifications/{id}/read
Marca una notificación específica como leída.
- **Persistencia**: Actualiza el estado en la base de datos para que no reaparezca en el feed del usuario.
- **Cuerpo de la Petición**: Vacío.
```bash
# Enviar calificación de 90%
curl -X POST "http://localhost:3002/grades" \
-H "Authorization: Bearer $TOKEN" \
-d '{"course_id": "...", "lesson_id": "...", "score": 0.9}'
```
---
### 4. IA y Analíticas Avanzadas
Funcionalidades inteligentes 100% locales y gratuitas.
#### POST /lessons/{id}/transcribe
Inicia el proceso de transcripción y traducción para una lección de video/audio.
#### POST /audio/evaluate
Evalúa una respuesta oral del estudiante utilizando IA.
#### POST /lessons/{id}/generate-quiz
Genera un quiz basado en el contenido de la lección.
- **Cuerpo ( QuizAIRequest ):**
```json
{
"context": "focused on irregular verbs",
"quiz_type": "true-false"
}
```
#### POST /lessons/{id}/dependencies
Asigna una lección como prerrequisito de otra.
- **Cuerpo ( LessonDependencyRequest ):**
```json
{
"prerequisite_lesson_id": "uuid",
"min_score_percentage": "number (opcional)"
}
```
#### GET /lessons/{id}/dependencies
Lista los prerrequisitos de una lección específica.
#### DELETE /lessons/{lesson_id}/dependencies/{prereq_id}
Elimina un prerrequisito de una lección.
#### DELETE /courses/{id}
Elimina un curso y todos sus contenidos relacionados (módulos, lecciones, assets).
- **Procesamiento Asíncrono**: Despacha una tarea en segundo plano que utiliza Whisper para transcripción y Ollama para generar la traducción y el resumen inteligente.
- **Cuerpo de la Petición**: Vacío.
#### GET /lessons/{id}/feedback
Obtiene retroalimentación personalizada de IA basada en el desempeño del estudiante y el contexto de la lección.
- **Uso Crítico**: Se llama automáticamente cuando una lección calificada es bloqueada por intentos agotados.
- **Respuesta**: Un objeto JSON con la respuesta motivacional del tutor.
#### POST /lessons/{id}/chat
Interactúa con el tutor de IA específico para la lección.
- **Contexto Inteligente**: La IA tiene acceso a la transcripción del video, el contenido de los bloques interactivos y el historial de lecciones pasadas del curso.
- **Cuerpo ( ChatPayload ):**
```json
{
"message": "string"
}
```
#### GET /lessons/{id}/vtt?lang=en|es
Devuelve los subtítulos en formato WebVTT para integración nativa.
- **Internacionalización**: Filtra los subtítulos por el parámetro `lang` y los devuelve con el formato de tiempo compatible con reproductores de video HTML5.
- **Respuesta**: Archivo de texto WebVTT.
#### POST /chat (Streaming)
Conversación en tiempo real con la base de conocimientos.
- **Nueva Sesión**: Omite `session_id`. La API creará uno nuevo y generará un título automático.
- **Continuar Sesión**: Envía el `session_id` devuelto anteriormente.
- **RAG (Base de Conocimiento)**: Envía `"use_kb": true` para que la IA busque en los documentos de S3.
- **Cuerpo ( ChatPayload ):**
```json
{
"username": "string",
"prompt": "string",
"session_id": "uuid (opcional)",
"use_kb": "boolean"
}
```
```bash
# Iniciar chat con RAG
curl -X POST "http://localhost:8000/chat" \
-H "Content-Type: application/json" \
-d '{
"username": "juan",
"prompt": "Explícame qué es Docker en una frase",
"use_kb": true
}'
```
**Respuesta**: Stream de texto plano. Al final incluye un JSON con el ID de sesión: `{"session_id": "..."}`.
#### GET /courses/{id}/analytics/advanced
Métricas de retención y análisis de cohortes para un curso.
- **Inteligencia de Datos**: Cruza información de intentos de evaluaciones y tiempos de visualización para identificar patrones de deserción.
- **Respuesta**: Dashboard JSON con métricas agregadas.
#### GET /lessons/{id}/heatmap
Devuelve los puntos de concentración de visualización para una lección.
- **Engagement Visual**: Analiza los eventos de heartbeat para determinar cuáles segundos del video son los más vistos o repetidos por los estudiantes.
- **Respuesta**: Array de `(second, count)`.
#### GET /courses/{id}/analytics/reports
Generador de reportes personalizados para exportación.
- **Flexibilidad Administrativa**: Permite filtrar el desempeño por cohortes específicas y devuelve la estructura necesaria para generar archivos CSV profesionales.
- **Respuesta**: Stream de datos o estructura de reporte.
#### GET /courses/{id}/dropout-risks
Obtiene el reporte de riesgo de abandono para todos los estudiantes del curso.
- **Inteligencia Predictiva**: Calcula en tiempo real (o consulta caché) el nivel de riesgo (Critical, High, Medium, Low) basándose en promedios, frecuencia de actividad y participación en foros.
- **Seguridad**: Solo accesible para usuarios con rol `instructor` o `admin`.
- **Respuesta**: Array de objetos `DropoutRisk`.
---
### 5. Discussion Forums (Foros de Discusión)
Sistema completo de foros por curso con hilos, respuestas anidadas y moderación.
#### GET /courses/{id}/discussions
Lista todos los hilos de discusión de un curso.
- **Filtros Disponibles**:
- `filter=all`: Todos los hilos (por defecto)
- `filter=my_threads`: Solo hilos creados por el usuario
- `filter=unanswered`: Hilos sin respuestas
- `filter=resolved`: Hilos con respuestas marcadas como correctas
- `lesson_id={uuid}`: Filtrar por lección específica
- **Paginación**: `page=1` (50 hilos por página)
- **Respuesta**: Array de `ThreadWithAuthor` con información del autor y estadísticas agregadas.
```bash
# Listar hilos sin responder
curl "http://localhost:3002/courses/{course_id}/discussions?filter=unanswered" \
-H "Authorization: Bearer $TOKEN"
```
#### POST /courses/{id}/discussions
Crea un nuevo hilo de discusión.
- **Auto-suscripción**: El autor se suscribe automáticamente para recibir notificaciones.
- **Cuerpo ( CreateThreadPayload ):**
```json
{
"title": "string",
"content": "string",
"lesson_id": "uuid (opcional)"
}
```
#### GET /discussions/{id}
Obtiene un hilo completo con todas sus respuestas anidadas.
- **Contador de Vistas**: Incrementa automáticamente el `view_count`.
- **Árbol de Respuestas**: Las respuestas se devuelven en estructura jerárquica con anidación infinita.
- **Respuesta**: Objeto con `thread` y `posts` (árbol de respuestas).
#### POST /discussions/{id}/posts
Crea una respuesta en un hilo.
- **Respuestas Anidadas**: Usa `parent_post_id` para responder a un post específico.
- **Validación**: No permite responder si el hilo está bloqueado.
- **Cuerpo ( CreatePostPayload ):**
```json
{
"content": "string",
"parent_post_id": "uuid (opcional, null para respuesta directa al hilo)"
}
```
#### POST /posts/{id}/vote
Vota por una respuesta (upvote/downvote).
- **Lógica**: Un usuario solo puede votar una vez por post. Cambiar el voto actualiza el registro existente.
- **Recalculo Automático**: El contador de upvotes se actualiza inmediatamente.
- **Cuerpo ( VotePayload ):**
```json
{
"vote_type": "upvote" // o "downvote"
}
```
#### POST /posts/{id}/endorse (Solo Instructores)
Marca una respuesta como correcta/aprobada.
- **Indicador Visual**: Las respuestas endorsadas aparecen primero en la lista.
- **Permiso**: Solo instructores y administradores pueden endorsar.
#### POST /discussions/{id}/pin (Solo Instructores)
Fija/desfija un hilo en la parte superior de la lista.
- **Uso**: Para destacar anuncios importantes o FAQs.
- **Permiso**: Solo instructores y administradores.
#### POST /discussions/{id}/lock (Solo Instructores)
Bloquea/desbloquea un hilo para prevenir nuevas respuestas.
- **Uso**: Para cerrar discusiones resueltas o inapropiadas.
- **Permiso**: Solo instructores y administradores.
#### POST /discussions/{id}/subscribe
Suscribe al usuario a las notificaciones del hilo.
- **Notificaciones**: El usuario recibirá alertas cuando haya nuevas respuestas.
#### POST /discussions/{id}/unsubscribe
Cancela la suscripción del usuario al hilo.
```bash
# Crear hilo
curl -X POST "http://localhost:3002/courses/{course_id}/discussions" \
-H "Authorization: Bearer $TOKEN" \
-d '{"title": "Pregunta sobre Módulo 2", "content": "No entiendo la sección de..."}'
# Responder a hilo
curl -X POST "http://localhost:3002/discussions/{thread_id}/posts" \
-H "Authorization: Bearer $TOKEN" \
-d '{"content": "Aquí está mi respuesta..."}'
# Votar respuesta
curl -X POST "http://localhost:3002/posts/{post_id}/vote" \
-H "Authorization: Bearer $TOKEN" \
-d '{"vote_type": "upvote"}'
```
---
### 5. Anuncios del Curso (Announcements)
| Acción | Método | Endpoint | Descripción |
|--------|--------|----------|-------------|
| Listar | GET | `/courses/{id}/announcements` | Obtiene todos los anuncios de un curso |
| Crear | POST | `/courses/{id}/announcements` | Crea un nuevo anuncio (Solo Instructor/Admin) |
| Actualizar | PUT | `/announcements/{id}` | Actualiza un anuncio (Solo Instructor/Admin) |
| Eliminar | DELETE| `/announcements/{id}` | Elimina un anuncio (Solo Instructor/Admin) |
#### Ejemplo de Creación de Anuncio
```bash
curl -X POST http://localhost:3002/courses/{course_id}/announcements \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Bienvenida al curso",
"content": "Bienvenidos a todos a este emocionante curso.",
"is_pinned": true
}'
```
---
### 6. Estructura Single-Tenant
OpenCCB está diseñado como un módulo premium single-tenant. Todas las operaciones se realizan bajo una única organización preconfigurada.
#### Organización por Defecto
- **ID de Organización**: `00000000-0000-0000-0000-000000000001`
- El sistema utiliza este ID de forma transparente para todas las consultas y recursos.
#### Branding Unificado
- La personalización de marca se aplica globalmente a través del panel de Ajustes en Studio, afectando tanto a la interfaz administrativa como al portal del estudiante.
---
## 🏆 Componentes UI Premium
- **Advanced Grading (Rubrics)**: Sistema completo de evaluación por rúbricas configurables.
- **Content Libraries**: Repositorio reutilizable de bloques y lecciones para máxima eficiencia.
- **Course Portability**: Sistema de importación/exportación basado en JSON para movilidad de contenidos.
- **AI Course Wizard**: Generación instantánea de currículos a partir de prompts.
- **Global Admin Console**: Control centralizado para organizaciones, usuarios y registros de auditoría.
- **Experience Player**: Interfaz de aprendizaje de alto rendimiento y accesible con diseño glassmorphism.
- **Organization Selector**: Combobox con búsqueda para gestionar grandes listas de inquilinos.
- **Engagement Heatmaps**: Gráficos dinámicos que muestran la retención en videos.
- **Notification Center**: Alertas en tiempo real para fechas límite y logros.
- **Custom Report Builder**: Reportes profesionales con exportación a CSV en un clic.
- **Glassmorphism Design**: Estética consistente en los portales Studio y Experience.
- **Global Localization**: Soporte nativo para Inglés, Español y Portugués.
- **PDF Integrated Viewer**: Lectura de documentos académicos sin salir de la plataforma.
- **Interactive Video Markers**: Preguntas que pausan el video integradas en las lecciones.
- **White-Label Branding**: Nombre de plataforma, logo, favicon y temas de color personalizados por organización.
- **Dynamic LAN Connectivity**: Detección automática de la IP del servidor para acceso fluido multi-dispositivo.
- **Mobile-First Navigation**: Menús laterales responsivos y diseños adaptativos para todas las pantallas.
- **Context-Aware AI Tutor**: Asistente inteligente con RAG que recuerda lecciones pasadas y protege respuestas.
- **Personalized AI Feedback**: Retroalimentación motivacional e instruccional generada únicamente para cada estudiante.
- **Color-Coded Navigation**: Indicadores visuales de progreso en tiempo real (Verde/Amarillo/Rojo).
- **Discussion Forums**: Sistema completo de foros con hilos, votos, moderación y suscripciones.
- **Course Announcements**: Sistema de comunicación instructor-estudiante con notificaciones automáticas.
- **Split Authentication**: Flujos de inicio de sesión separados para usuarios personales y empresas con soporte SSO.
- **Mercado Pago Monetization**: Pasarela de pagos integrada con desbloqueo automático de cursos.
- **Student Notes Panel**: Anotaciones personales con interfaz glassmorphism y autoguardado inteligente.
- **Cohort Management**: Sistema de gestión de grupos con seguimiento de progreso por cohorte.
- **Advanced Gradebook**: Seguimiento del desempeño estudiantil con analíticas y filtrado avanzado.
- **Learning Sequences UI**: Interfaz visual para gestionar dependencias y visualización de bloqueos con iconos de candado.
- **Student Progress Dashboard**: Panel de control con gráficos interactivos (Recharts) que muestran la actividad de aprendizaje y estiman el tiempo restante del curso.
- **Course Teams UI**: Panel de gestión para añadir y configurar roles de instructores secundarios y asistentes.
- **Course Preview Badges**: Indicadores visuales y lógica de acceso para lecciones accesibles sin suscripción.
- **Global Asset Manager**: Interfaz avanzada para la administración masiva de archivos con previsualización inteligente y filtros por curso o tipo.
- **Premium Course Summaries**: Presentación de cursos con diseño de alta fidelidad y desgloses de objetivos de aprendizaje.
Para una guía detallada sobre cómo integrar o extender OpenCCB, consulta la documentación técnica:
- 📘 [Referencia de la API](docs/API.md)
- ⚙️ [Manual de Configuración](ManualDeConfiguracion.md)
- 🏗️ [Guía de Despliegue](DESPLIEGUE.md)
---
## 📊 Estado de Funcionalidades
OpenCCB es una plataforma madura con la mayoría de sus funcionalidades core implementadas y operativas. Esta sección documenta transparentemente el estado actual de las características principales para que desarrolladores y administradores puedan planificar su uso.
### ✅ Implementado
- CRUD de Cursos e IA Generation.
- 16+ tipos de bloques interactivos.
- Sistema de foros, anuncios y gamificación.
- Soporte LTI 1.3 y SSO (OIDC).
- Monetización con Mercado Pago.
### ✅ Completamente Implementado
| Categoría | Funcionalidades |
|-----------|-----------------|
| **Gestión de Cursos** | CRUD completo, AI generation, export/import JSON, templates, marketing metadata, teams, preview tokens |
| **Contenidos** | 16 tipos de bloques (video, quiz, hotspot, memory, mermaid, code lab, etc.) |
| **IA Integrada** | Transcripción, traducción, resúmenes, quiz generation, tutor RAG, audio evaluation, diagramas |
| **Question Bank** | CRUD completo, semantic search (PGVector), duplicate detection, AI generation con 4 skills |
| **Calificaciones** | Rubrics, weighted categories, drop-lowest policy, gradebook con cohortes, export CSV |
| **Foros** | Hilos, respuestas anidadas, votos, endorsements, moderación, suscripciones |
| **Gamificación** | XP, niveles, badges, leaderboards, Open Badges |
| **Monetización** | Mercado Pago integration, pricing, webhooks, auto-enrollment |
| **LTI 1.3** | Tool Provider con Deep Linking, JWKS, autoprovisionamiento |
| **Live Learning** | Integración Jitsi, scheduling desde Studio |
| **Analíticas** | Dashboard instructores, heatmaps, dropout risk prediction, advanced analytics |
| **Single-Tenant** | White-label branding, SSO/OIDC, exercise settings |
| **Responsive UI** | Mobile-first, dynamic API resolution, fluid typography |
### ⚠️ En Progreso / Pendiente de Finalización
| Funcionalidad | Estado Actual | Impacto |
|---------------|---------------|---------|
| **Generación de Certificados** | Schema de BD existe, falta implementación de generación y UI | Los estudiantes que completan cursos no reciben certificado |
| **Tracking de Progreso** | Hardcodeado a 0% en `my-learning/page.tsx` | Los estudiantes no ven su progreso real en el catálogo |
| **Notificaciones de Foros** | Suscripciones existen pero no se envían alertas | Usuarios suscritos no reciben notificaciones de respuestas |
| **Importación Excel (Question Bank)** | Código comentado con `unimplemented!()` | Solo se puede importar manualmente o vía AI |
| **Rate Limiting** | Deshabilitado por compatibilidad con middleware | APIs sin protección contra abuso en producción |
### 📋 Planned (Ver roadmap.md para detalles)
| Funcionalidad | Descripción |
|---------------|-------------|
| **Email/SMTP Integration** | Notificaciones por email, password reset, welcome emails |
| **Búsqueda Global** | Search unificado en cursos, lecciones, contenidos |
| **SCORM/xAPI Support** | Importación de paquetes SCORM, tracking xAPI |
| **Accesibilidad WCAG 2.1** | Auditoría y correcciones de contraste, navegación por teclado |
| **PWA y Offline** | Service workers, descarga de lecciones, sync offline |
| **Integraciones Empresariales** | HRIS (Workday, SAP), LDAP/Active Directory, webhooks salientes |
> [!NOTE]
> Si encuentras alguna funcionalidad marcada como "En Progreso" que necesitas urgentemente, por favor abre un issue en el repositorio o contribuye con un PR. ¡Las contribuciones son bienvenidas!
### ⚠️ En Desarrollo
- **Generación de Certificados**: Implementando lógica de PDF automático.
- **Progreso Real**: Refactorizando visualización en catálogo.
- **Email/SMTP**: Integración de notificaciones transaccionales.
---
## 📚 Documentación
## 📈 Roadmap
### Guías Principales
| Archivo | Descripción |
|---------|-------------|
| **README.md** | Este archivo - Visión general y características |
| **roadmap.md** | Hoja de ruta completa del proyecto (Fases 1-21) |
| **ManualDeConfiguracion.md** | Guía completa de instalación, configuración y troubleshooting |
### Comandos Rápidos
```bash
# Instalación estándar (detecta dev/prod automáticamente)
./install.sh
# Instalación rápida (omite chequeos)
./install.sh --fast
# Despliegue a producción (sincroniza con servidor remoto)
./install.sh --deploy
# Iniciar servicios
docker-compose up -d
# Ver logs
docker-compose logs -f
# Health checks
curl http://localhost:3001/health
curl http://localhost:3002/health
```
### URLs de Acceso
| Servicio | Puerto | URL |
|----------|--------|-----|
| **Studio (CMS)** | 3000 | http://localhost:3000 |
| **Experience (LMS)** | 3003 | http://localhost:3003 |
| **CMS API** | 3001 | http://localhost:3001 |
| **LMS API** | 3002 | http://localhost:3002 |
### Credenciales por Defecto
Después de ejecutar `./install.sh`:
- **Email**: `admin@norteamericano.cl`
- **Contraseña**: `Admin123!`
---
## Próximos Pasos (Roadmap 2024-2025)
OpenCCB evoluciona constantemente. Estos son los pilares de nuestro desarrollo futuro:
### 📱 Movilidad Nativa
- **Apps Android/iOS**: Aplicaciones nativas desarrolladas con Flutter para aprendizaje offline y notificaciones push críticas.
- **Offline Sync**: Capacidad de descargar lecciones y sincronizar progreso al recuperar conexión.
### 🧠 Inteligencia Artificial Avanzada
- **AI Video Generation (v1)**: ✅ Generación de clips a partir de prompts y guiones de lecciones.
- **AI Proctoring**: Monitoreo basado en visión artificial para exámenes de alta integridad, 100% privado y local.
- **Multimodal Tutoring**: El tutor de IA podrá analizar imágenes y videos subidos por el alumno para dar feedback.
- **Automated Grading for Open Questions**: Evaluación masiva de ensayos y respuestas abiertas con rúbricas personalizadas.
### 🔌 Interoperabilidad y Estándares
- **SCORM 1.2 / 2004 Support**: Player nativo para contenidos legados de la industria.
- **Advanced xAPI (Tin Can)**: Recolección detallada de experiencias de aprendizaje granulares.
- **Microsoft Teams / Slack Integration**: Recibe anuncios y tareas directamente en tus herramientas de trabajo.
### 🏗️ Infraestructura y Escalabilidad
- **Multi-Cloud Terraform Provider**: Despliegues automatizados en AWS, GCP y Azure.
- **Edge Content Delivery**: Caché de videos y assets en el borde para mínima latencia global.
### 🎮 Gamificación y Comunidad
- **Real-time Leaderboards**: Tablas de clasificación en vivo por cohorte y organización.
- **Social Learning Groups**: Grupos de estudio auto-organizados con chats integrados.
OpenCCB evoluciona constantemente. Consulta el [roadmap.md](roadmap.md) para ver el plan detallado de las Fases 22 a 36, incluyendo IA de Moderación y Ecosistemas de Plugins.
---
## 📄 Licencia
## 📄 Licencia
Este proyecto es código abierto y está disponible bajo los términos de la licencia especificada en el repositorio.
+18 -1
View File
@@ -389,6 +389,12 @@ echo " SSL Staging: $LETSENCRYPT_STAGING"
echo " Preservar SSL: $PRESERVE_SSL_CERTS"
echo " Reiniciar DB: $RESET_DATABASE"
echo " Compilar local: $BUILD_LOCAL"
# Detectar variables de integración desde .env local para el resumen
_SAM_URL=$(grep '^SAM_DIAGNOSTICO_DATABASE_URL=' .env | cut -d'=' -f2-)
_MYSQL_URL=$(grep '^MYSQL_DATABASE_URL=' .env | cut -d'=' -f2-)
echo " SAM Integration: ${_SAM_URL:-(No configurada)}"
echo " MySQL Legacy: ${_MYSQL_URL:-(No configurada)}"
echo ""
# Crear script remoto en un archivo temporal
@@ -528,6 +534,15 @@ if ! grep -q "^AWS_SECRET_ACCESS_KEY=" .env; then
echo "AWS_SECRET_ACCESS_KEY=" >> .env
fi
# Conservar o inicializar variables de integración
echo " Configurando variables de integración (SAM/MySQL)..."
if ! grep -q "^SAM_DIAGNOSTICO_DATABASE_URL=" .env; then
echo "SAM_DIAGNOSTICO_DATABASE_URL=" >> .env
fi
if ! grep -q "^MYSQL_DATABASE_URL=" .env; then
echo "MYSQL_DATABASE_URL=" >> .env
fi
# Asegurar dominios públicos para nginx-proxy y certificados SSL
sed -i "/^NEXT_PUBLIC_STUDIO_DOMAIN=/d" .env 2>/dev/null || true
sed -i "/^NEXT_PUBLIC_LEARNING_DOMAIN=/d" .env 2>/dev/null || true
@@ -961,7 +976,8 @@ sleep 10
# Intentar crear el usuario via API
echo "Creando usuario administrador..."
ADMIN_RESPONSE=$($DOCKER_CMD exec \
if [ -n "$ADMIN_EMAIL" ] && [ -n "$ADMIN_PASS" ]; then
ADMIN_RESPONSE=$($DOCKER_CMD exec \
-e ADMIN_EMAIL="$ADMIN_EMAIL" \
-e ADMIN_PASS="$ADMIN_PASS" \
-e ADMIN_NAME="$ADMIN_NAME" \
@@ -1004,6 +1020,7 @@ else
echo "Detalle: $ADMIN_BODY"
fi
fi
fi
echo ""
echo "========================================"
+140
View File
@@ -0,0 +1,140 @@
# Referencia de API de OpenCCB
Esta guía proporciona detalles técnicos sobre los endpoints disponibles en OpenCCB para desarrolladores e integradores.
## 1. Autenticación y Cuentas
Gestión de registro, login y perfiles organizacionales.
### POST /auth/register
Crea un nuevo usuario vinculado a la organización por defecto.
- **Cuerpo de la Petición ( AuthPayload ):**
```json
{
"email": "string",
"password": "string",
"full_name": "string",
"role": "string (admin | instructor | student)"
}
```
### SSO (OpenID Connect)
OpenCCB soporta integración con proveedores de identidad (IdP) externos como Google, Okta y Azure AD.
- **Configuración**: Los administradores de la organización pueden configurar sus credenciales OIDC en el panel de configuración de Studio.
- **Autoprovisionamiento**: Los nuevos usuarios se crean automáticamente en la plataforma tras una autenticación exitosa.
### LTI 1.3 e Interoperabilidad
OpenCCB actúa como un Tool Provider LTI 1.3 moderno, utilizando OIDC y JWKS para máxima seguridad.
- **JWKS Endpoint**: `/lti/jwks` expone las claves públicas para verificación de firmas.
- **Deep Linking**: Permite que instructores seleccionen cursos o lecciones específicas desde el LMS externo mediante una interfaz de Studio embebida.
- **Autoprovisionamiento**: Los usuarios lanzados vía LTI se crean automáticamente con los roles correspondientes.
```bash
# Registrar un nuevo administrador
curl -X POST "http://localhost:3001/auth/register" \
-H "Content-Type: application/json" \
-d '{"email": "admin@empresa.com", "password": "pass", "full_name": "Admin Name"}'
```
---
## 2. Gestión de Contenidos (CMS)
Herramientas para instructores y administradores.
### POST /courses
Crea un nuevo curso vinculado a la organización del usuario.
- **Lógica**: El `instructor_id` se asigna automáticamente desde el token JWT.
- **Cuerpo ( CreateCourseRequest ):**
```json
{
"title": "string",
"pacing_mode": "string (self_paced | instructor_led)"
}
```
```bash
# Crear curso básico
curl -X POST "http://localhost:3001/courses" \
-H "Authorization: Bearer $TOKEN" \
-d '{"title": "Curso de Rust", "pacing_mode": "self_paced"}'
```
### POST /courses/generate
Utiliza IA para generar la estructura completa de un curso basado en un prompt.
### GET /courses/{id}/export
Exporta un curso completo y su contenido a formato JSON para portabilidad.
### POST /courses/import
Importa un curso a partir de un archivo JSON generado previamente.
### POST /lessons
Agrega contenido multimedia o evaluaciones a un módulo.
- **Configuración Graduable**: Si `is_graded` es true, los puntos sumarán al XP del estudiante en el LMS.
- **Nuevos Tipos Gamificados**:
- `hotspot`: Identificación visual sobre imágenes.
- `memory-match`: Juego de memoria con pares conceptuales.
- `video-marker`: Preguntas interactivas en timestamps específicos del video.
### POST /assets/upload
Sube un archivo multimedia o documento a la biblioteca global de la organización.
---
## 3. Experiencia de Aprendizaje (LMS)
Endpoints para estudiantes y seguimiento de progreso.
### POST /enroll
Inscribe al usuario en un curso.
### POST /grades
Registra el puntaje de una lección y actualiza la gamificación.
### GET /notifications
Obtiene las notificaciones pendientes del usuario.
---
## 4. IA y Analíticas Avanzadas
Funcionalidades inteligentes 100% locales y gratuitas.
### POST /lessons/{id}/transcribe
Inicia el proceso de transcripción y traducción.
### POST /audio/evaluate
Evalúa una respuesta oral del estudiante utilizando IA.
### POST /lessons/{id}/generate-quiz
Genera un quiz basado en el contenido de la lección.
### POST /chat (Streaming)
Conversación en tiempo real con la base de conocimientos (RAG).
### GET /lessons/{id}/heatmap
Devuelve los puntos de concentración de visualización para una lección.
---
## 5. Foros de Discusión (Discussion Forums)
Sistema completo de foros por curso con hilos, respuestas anidadas y moderación.
### GET /courses/{id}/discussions
Lista todos los hilos de discusión de un curso.
### POST /courses/{id}/discussions
Crea un nuevo hilo de discusión.
### POST /posts/{id}/vote
Vota por una respuesta (upvote/downvote).
---
## 6. Anuncios del Curso (Announcements)
| Acción | Método | Endpoint |
|--------|--------|----------|
| Listar | GET | `/courses/{id}/announcements` |
| Crear | POST | `/courses/{id}/announcements` |
| Eliminar | DELETE| `/announcements/{id}` |
+88 -458
View File
@@ -3,492 +3,122 @@
## Fase 1: Cimientos ✅
- [x] Configuración del Workspace de Rust (Edición 2024)
- [x] Estructura de Microservicios (CMS y LMS)
- [x] Infraestructura Multi-Base de Datos (PostgreSQL con DBs separadas)
- [x] Inicialización del Frontend (Studio y Experience con Next.js)
- [x] Dockerización de todos los servicios
- [x] Integración de API (Dashboard <-> Servicio CMS)
- [x] Script de instalación unificado (`install.sh`) con detección de hardware y auto-configuración
- [x] Infraestructura Multi-Base de Datos
- [x] Inicialización del Frontend (Studio y Experience)
- [x] Dockerización y Script de instalación unificado
## Fase 2: Funcionalidades Core del CMS ✅
- [x] Editor de Estructura de Cursos (Módulos y Lecciones)
- [x] Sistema de Carga de Archivos (Video, Audio, Recursos Nativos)
- [x] Contenido Interactivos (Constructor de Actividades)
- [x] Reordenamiento de bloques (Subir/Bajar)
- [x] Descripciones con texto enriquecido
- [x] Bloques multimedia con restricciones de reproducción
- [x] Bloques de Quiz (Opción múltiple, Verdadero/Falso, Selección múltiple)
- [x] Tipos de evaluación avanzada:
- [x] Completar espacios en blanco
- [x] Emparejamiento de parejas
- [x] Ordenamiento/Secuenciación
- [x] Respuesta corta
- [x] Comunicación entre servicios (Sincronización CMS -> LMS)
- [x] Reproductor de video Premium con límites de visualización
- [x] Interfaz de Studio completa con gestión dinámica de cursos
- [x] Editor de Estructura de Cursos
- [x] Sistema de Carga de Archivos
- [x] Constructor de Actividades Interactivas
- [x] Tipos de evaluación avanzada (Secuenciación, Emparejamiento, etc.)
## Fase 3: Autenticación y Seguridad ✅
- [x] **Autenticación Basada en JWT**: Auth común para todos los servicios
- [x] **Control de Acceso Basado en Roles (RBAC)**:
- [x] Soporte multi-rol (Admin, Instructor, Estudiante)
- [x] Permisos e interfaces específicas por rol
- [x] Autorización basada en tokens para endpoints protegidos
- [x] **Registro de Auditoría (Audit Log)**: Seguimiento de todos los cambios en el CMS
- [x] **Interfaz de Auditoría**: Panel de administración para visualizar registros de cambios
- [x] Autenticación basada en JWT
- [x] Control de Acceso Basado en Roles (RBAC)
- [x] Registro e Interfaz de Auditoría
## Fase 4: Experiencia LMS y Calificaciones ✅
- [x] **Portal del Estudiante (Experience)**:
- [x] Catálogo de cursos e inscripciones
- [x] Reproductor interactivo de lecciones
- [x] Diseño responsivo (móviles/tablets) - **Optimizado y validado en Fase 15**
- [x] **Sistema de Calificación Holístico**:
- [x] Categorías de calificación con pesos (porcentajes)
- [x] Opción de eliminar las N puntuaciones más bajas por categoría
- [x] Cálculo automático de la nota ponderada
- [x] **Políticas de Evaluación**:
- [x] Intentos máximos configurables por lección
- [x] Correcciones instantáneas y políticas de reintento
- [x] Seguimiento atómico de intentos con validación de reglas
- [x] **Seguimiento del Progreso**:
- [x] Visualización de puntuaciones en tiempo real
- [x] Desglose categoría por categoría
- [x] **Umbrales de Aprobación Dinámicos**:
- [x] Porcentaje de aprobación configurable por curso
- [x] Visualización de rendimiento en 5 niveles
- [x] Feedback por colores (desde Reprobado hasta Excelente)
- [x] **Certificados**: Generación automática de certificados al completar el curso
- [x] Portal del Estudiante (Experience)
- [x] Sistema de Calificación Holístico con pesos
- [x] Políticas de Evaluación e Intentos
- [x] Umbrales de Aprobación Dinámicos
- [x] Generación de Certificados básicos
## Fase 5: Analíticas e Insights ✅
- [x] **Dashboard de Analíticas para Instructores**:
- [x] Total de inscritos por curso
- [x] Promedio general de notas
- [x] Desglose de rendimiento por lección
- [x] Detección de "lecciones difíciles"
- [x] Aplicación de RBAC (los instructores solo ven sus cursos)
- [x] **Dashboard de Progreso del Estudiante**:
- [x] Barra de rendimiento interactiva
- [x] Visualización de feedback basada en niveles
- [x] Actualización de notas en tiempo real
- [x] Dashboard de Analíticas para Instructores
- [x] Dashboard de Progreso del Estudiante
## Fase 6: Refactorización a Single-Tenant ✅
- [x] **Single-tenancy**: Reposicionamiento como módulo premium (Completado)
- [x] Hardcoding del `organization_id` por defecto en middleware común
- [x] Remoción de selectores de organización en Studio y Experience
- [x] Simplificación de registros y logins para un solo inquilino
- [x] Eliminación de rutas y controladores de gestión multi-empresa
- [x] Limpieza de componentes frontend redundantes (Selector, Gestión de Orgs)
- [x] **Personalización de Marca (Branding Premium)**: Identidad unificada (Completado)
- [x] Endpoints singulares para gestión de marca sin parámetros de ID
- [x] Carga y optimización de logotipos y favicons customizados
- [x] Nombre de plataforma personalizado (White-label)
- [x] Esquemas de colores personalizados aplicado globalmente
- [x] Previsualización en vivo del branding en Studio renovada
- [x] **Interfaz de Usuario Simplificada**:
- [x] **Login Unificado**: Eliminación de flujo dividido Personas/Empresas
- [x] **Navegación Limpia**: Remoción de enlaces de administración de organizaciones
- [x] Reposicionamiento como módulo premium
- [x] Personalización de Marca (Branding Premium)
- [x] Interfaz de Usuario e Inicio de Sesión Simplificados
## Fase 7: Compromiso y Social (En Progreso)
- [x] **Analíticas de Vanguardia**:
- [x] Análisis de cohortes (Implementado)
- [x] Métricas de retención (Implementado)
- [x] Mapas de calor de participación (Heatmaps) (Implementado)
- [x] **Integración de IA**:
- [x] Resúmenes de lecciones generados por IA (Llama 3)
- [x] Generación automática de quices (Llama 3)
- [ ] Transcripción y traducción de video en tiempo real (Postpuesto - Reemplazado por Llama 3 para otras funciones)
- [x] **Rutas de Aprendizaje Personalizadas**: Recomendaciones impulsadas por Llama 3 (Implementado)
- [x] **Gamificación Base**: (Implementada a nivel de sistema)
- [x] Medallas y logros
- [x] Tablas de clasificación (Leaderboards)
- [x] Sistema de XP y niveles
- [x] **Mejoras en la Gestión de Cursos**:
- [x] Nombrado manual de módulos, lecciones y actividades
- [x] Pacing de cursos: Modo autodidacta (Evergreen) o Dirigido por instructor (Cohort)
## Fase 7: Compromiso y Social
- [x] Analíticas de Vanguardia (Cohortes, Retención, Heatmaps)
- [x] Integración de IA (Resúmenes, Quices, Tutor RAG)
- [x] Rutas de Aprendizaje Personalizadas
- [x] Gamificación Base (XP, Niveles, Leaderboards)
- [x] Calendario de hitos y recordatorios automáticos de fechas límite
## Fase 8: Funcionalidades Enterprise (En Progreso)
- [x] **Perfil de Usuario y Ciclo de Vida**:
- [x] **Cierre de Sesión Integrado**: Gestión estandarizada en ambos portales
- [x] **Gestión del Perfil**: Actualización de avatar, bio e idioma por el usuario
- [x] **Reportes Avanzados**: Constructor de reportes personalizados y exportación a CSV (Implementado)
- [x] **Ecosistema de Integración**:
- [x] **SSO (Single Sign-On)**: Soporte completo OIDC (Google, Okta, Azure AD) (Completado)
- [x] **LTI 1.3 Tool Provider**: Integración segura con LMS externos como Canvas o Moodle (Completado)
- [ ] **Accesibilidad**: Auditoría y correcciones WCAG 2.1
## Fase 8: Funcionalidades Enterprise ✅
- [x] Perfil de Usuario y Ciclo de Vida
- [x] Reportes Avanzados exportables a CSV
- [x] SSO (Google, Okta, Azure AD)
- [x] LTI 1.3 Tool Provider (Interoperabilidad)
## Fase 9: Portabilidad de Cursos ✅
- [x] **Esquema JSON Universal**: Formato estandarizado para intercambio de cursos (Completado)
- [x] **Exportador Recursivo**: Serialización de jerarquías completas de cursos (Completado)
- [x] **Importador Atómico**: Creación por lotes con re-mapeo de dependencias (Completado)
- [x] **Interfaz de Portabilidad**: Botones de Exportación/Importación en Ajustes (Completado)
- [x] Esquema JSON Universal y Portabilidad de contenidos
## Fase 10: Consola de Administración Global ✅
- [x] **Panel "Estilo Django"**: Interfaz dedicada para Super-Admins para gestionar Orgs y Usuarios (Completado)
- [x] **Monitoreo del Sistema**: Estadísticas en tiempo real de uso de IA y estado de servicios (Completado)
- [x] **Auditoría Universal**: Panel centralizado de actividad para todos los tenants (Completado)
- [x] Panel de control para organizaciones y auditoría universal
## Fase 11: Evaluaciones y Quizzes Extendidos (En Progreso)
- [x] **Quices de Código**: Desafíos interactivos con reproductor tipo IDE (Completado)
- [x] **Identificación Visual**: Quices de "Puntos Calientes" (Hotspots) en imágenes (Completado)
- [x] **Tutor de IA Integrado**: Asistente basado en RAG con acceso a bloques interactivos e historial del curso (Completado)
- [x] **Evaluaciones por Audio**: Preguntas con respuesta oral para idiomas con feedback de IA detallado (Completado)
- [x] **Eliminación de Cursos**: Gestión completa del ciclo de vida del contenido (Completado)
- [x] **Quices con Contexto IA**: Generación de evaluaciones con enfoque y tipo personalizable (Completado)
- [x] **Actividades Gamificadas**: Nuevos tipos de bloques interactivos incluyendo Juegos de Memoria (con generación automática por IA) y Puntos Calientes (Hotspots). (Completado)
- [x] **Marcadores de Video**: Preguntas que pausan el video en timestamps específicos (Completado)
## Fase 11 - 14: IA y Gamificación Avanzada ✅
- [x] Quices de Código y Puntos Calientes (Hotspots)
- [x] Evaluaciones por Audio con IA
- [x] Generador de Cursos "Mágico"
- [x] Juegos para niños e Internacionalización (EN, ES, PT)
## Fase 12: Generador de Cursos "Mágico" con IA
- [x] **Creación Instantánea**: Generación de estructura completa a partir de un prompt (Completado)
- [x] **Ingestión Atómica Transaccional**: Creación de módulos y lecciones en un solo paso (Completado)
- [x] **Ingeniería de Prompts**: Diseño curricular profesional optimizado para LLMs (Completado)
## Fase 15 - 19: UI Adaptativa y Monetización
- [x] Dynamic API Resolution (Acceso LAN)
- [x] Optimización móvil completa
- [x] Monetización con Mercado Pago
- [x] Analíticas Predictivas (Riesgo de Abandono)
- [x] Integración de Videoconferencia (Jitsi)
- [x] Landing Pages para Marketing de Cursos
## Fase 13: Gamificación para Niños
- [x] **Juego de Memoria**: Emparejamiento conceptual mediante cartas interactivas (Completado)
- [x] **Arrastrar al Cubo**: Categorización visual por arrastre (Completado)
- [x] **Feedback Animado**: Animaciones de celebración (confeti, estrellas) para éxitos (Completado)
## Fase 14: Globalización y Aprendizaje con Documentos ✅
- [x] **Internacionalización (i18n)**: Soporte de UI para Inglés, Español y Portugués (Completado)
- [x] **Selector de Idiomas**: Cambio dinámico en la barra de navegación y perfil (Completado)
- [x] **Bloque de Documentos**: Previsualización de PDF y descargas de DOCX/PPTX (Completado)
- [x] **IA Multi-idioma**: Las transcripciones y resúmenes siguen el contexto del curso (Completado)
## Fase 20 - 21: IA Generativa y Búsqueda Semántica
- [x] Diagramas Mermaid automáticos
- [x] Búsqueda Semántica con PGVector (Representación de 768 dim)
- [x] Detección de duplicados y RAG mejorado
---
## Fase 15: Conectividad y UI Adaptativa ✅
- [x] **Dynamic API Resolution**: Detección automática de IP del servidor para acceso multi-dispositivo y LAN (Completado)
- [x] **Menú Móvil (Experience)**: Implementación de navegación lateral (hamburger) para celulares (Completado)
- [x] **Optimización de Studio**: Interfaz de administración compacta y escalable para pantallas pequeñas (Completado)
- [x] **Tipografía Fluida**: Escalado de fuentes y márgenes adaptativos en todo el portal (Completado)
- [x] **Locked Lesson AI Feedback**: Generación de retroalimentación motivacional para lecciones bloqueadas (Completado)
- [x] **Context Enrichment**: Ingesta de bloques interactivos en el motor de RAG (Completado)
- [x] **Course History Context**: Capacidad del tutor para recordar lecciones previas (Completado)
- [x] **Color-Coded Progress Status**: Seguimiento visual por colores (Verde/Amarillo/Rojo) en sidebar y cabeceras (Completado)
## Fase 22: Estabilidad y Funcionalidades Pendientes 🛠️ (En Ejecución)
- [ ] **Generación de Certificados Premium**: Mejorar UI de configuración de templates en Studio.
- [ ] **Tracking de Progreso Atómico**: Reemplazar hardcodes por cálculo real de completitud.
- [ ] **Notificaciones de Foros**: Implementar despacho de alertas vía SMTP.
- [ ] **Importación Masiva (Excel)**: Finalizar soporte para Question Bank.
## Fase 16: Estabilidad y UX Avanzada ✅
- [x] **QA y Estabilidad**: Verificación del flujo completo de evaluación en entornos de producción.
- [x] **Rutas de Aprendizaje**: Recomendaciones basadas en el historial personalizadas y perfiles de habilidades.
- [x] **Optimización de Contenedores**: Limpieza automatizada y reducción de huella de infraestructura mediante Build Context optimizado.
- [x] **Split Login Flow**: Separación de flujos de autenticación para Personas y Empresas.
## Fase 17: Funcionalidades Estilo Open edX (En Progreso)
- [x] **Discussion Forums**: Sistema de foros por curso con hilos, respuestas anidadas y moderación.
- [x] Base de datos (4 tablas: threads, posts, votes, subscriptions)
- [x] Backend API (10 endpoints para gestión completa)
- [x] Permisos diferenciados (estudiante vs instructor)
- [x] Sistema de votación y endorsement
- [x] Frontend (componentes React)
- [x] Integración con notificaciones
- [x] **Course Announcements**: Sistema de anuncios de instructores con notificaciones.
- [x] **Student Notes**: Anotaciones personales por lección con exportación a PDF.
- [x] **Peer Assessment**: Evaluación entre pares con rúbricas configurables.
- [x] **Cohorts & Groups**: Segmentación de estudiantes con contenido específico.
- [x] **Content Libraries**: Repositorio reutilizable de bloques y lecciones.
- [x] **Advanced Grading**: Rúbricas detalladas y workflows de calificación.
- [x] **Learning Sequences**: Prerequisitos y rutas condicionales entre lecciones.
- [x] **Bulk Operations**: Bulk enrollment, advanced grade export, and segmented announcements.
- [x] **Course Teams**: Support for multiple instructors per course with granular roles.
- [x] **Course Preview**: Vista previa de lecciones sin inscripción.
- [x] **Bookmarks**: Sistema de favoritos para lecciones importantes.
- [x] **Progress Dashboard**: Gráficos de progreso temporal y predicción de finalización.
## Fase 18: Monetización y Estandarización ✅
- [x] **E-Commerce & Monetización**: (Completado)
- [x] Integración con Mercado Pago (Preferencia de pago y Webhooks).
- [x] Sistema de precios y moneda por curso.
- [x] Inscripción automática tras pago exitoso.
- [x] Verificación de seguridad de acceso a lecciones basada en inscripción.
- [x] Dashboard de transacciones básico en base de datos.
- [x] **Interoperabilidad**: ✅
- [x] Implementación de LTI 1.3 (Tool Provider) con soporte para Deep Linking.
- [x] Conectividad segura con LMS externos (Moodle/Canvas) via OIDC y JWKS.
- [x] **Analíticas Predictivas**: ✅
- [x] Motor de IA para detección de riesgo de abandono.
- [x] Notificaciones proactivas para instructores.
- [x] **Gestión de Activos**: ✅
- [x] Biblioteca de medios global (Global Asset Manager).
- [x] Reutilización de recursos multi-curso.
- [x] **Aprendizaje en Vivo**: ✅
- [x] Integración con Jitsi para aulas virtuales en tiempo real.
- [x] Gestión de reuniones y programación desde Studio.
- [x] Acceso directo para estudiantes desde Experience.
- [x] **Portafolio del Estudiante**: ✅
- [x] Sistema de medallas y logros (Open Badges).
- [x] Perfiles profesionales públicos con control de privacidad.
- [x] Visualización de progreso y nivel de XP.
## Fase 19: Presentación Visual y Marketing de Cursos ✅
- [x] **Metadatos de Marketing Estructurados**: Captura de objetivos, requisitos, público objetivo y certificación en Studio. (Completado)
- [x] **Premium Course Summary**: Nueva interfaz de "Acerca del Curso" en Experience con diseño de alta fidelidad y navegación por pestañas. (Completado)
- [x] **Dashboard Global de Tareas AI**: Panel unificado de control en consola administrativa para monitorear, reintentar y cancelar todas las generaciones en segundo plano (transcripciones, quices, juegos de memoria, etc). (Completado)
## Fase 23 - 27: Infraestructura Crítica 📋 (Planificado)
- [ ] **Integración SMTP**: Password reset, notificaciones transaccionales y de marketing.
- [ ] **Búsqueda Global Unificada**: Búsqueda full-text y semántica en toda la plataforma.
- [ ] **Soporte SCORM/xAPI**: Player nativo para contenidos legados.
- [ ] **Accesibilidad WCAG 2.1**: Auditoría y ajustes de contraste/navegación.
- [ ] **PWA y Soporte Offline**: Service workers para aprendizaje sin conexión.
---
**Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos** y **Landing Pages de Cursos (Marketing) automatizadas**.
## 🚀 Fases Estratégicas (Nuevas)
## Fase 20: IA Generativa Avanzada (En Ejecución) 🧠
- [x] **Generación de Juegos de Memoria Conceptuales**: Creación automática de parejas (concepto/definición) a partir de transcripciones. (Completado)
- [x] **Simulaciones de Rol y Diálogos Ramificados**: Motor de escenarios interactivos con respuestas dinámicas de la IA. (Completado)
- [x] **Auto-Hotspots Pedagógicos**: Identificación automática de puntos de interés en imágenes con descripciones técnicas. (Completado)
- [x] **Diagramas de Mermaid Dinámicos**: Visualización automática de procesos y mapas mentales a partir del contenido de la lección. (Completado)
- [x] **Laboratorios de Código con Hints de IA**: Generación de desafíos de programación con pistas contextuales basadas en errores. (Completado)
### Fase 32: IA de Moderación y Ética 🛡️
- [ ] **Auditoría de IA**: Sistema de validación para prevenir "halucinaciones" en el Tutor RAG.
- [ ] **Moderación Automática**: Detección de lenguaje ofensivo o inapropiado en foros y chats.
- [ ] **Ética de Datos**: Herramientas para transparencia en el uso de datos por los modelos de IA local.
### Fase 33: Aprendizaje Colaborativo Síncrono 🤝
- [ ] **Pizarras Compartidas**: Espacio de dibujo colaborativo integrado en lecciones.
- [ ] **Edición Multiusuario**: Soporte para documentos compartidos en tiempo real (tipo Google Docs).
- [ ] **Salas de Estudio**: Grupos efímeros para resolución de dudas grupales por video.
### Fase 34: Análisis Pedagógico Profundo 📊
- [ ] **Métricas de Calidad**: Análisis automático de la efectividad de las lecciones generadas.
- [ ] **Índice de Discriminación**: Estadísticas sobre qué preguntas de quiz discriminan mejor el conocimiento.
- [ ] **Sugerencias Curriculares**: IA recomendando cambios en la estructura del curso basada en el rendimiento real.
### Fase 35: Ecosistema de Plugins 🔌
- [ ] **Arquitectura Modular**: Sistema para que desarrolladores externos agreguen nuevos "Content Blocks".
- [ ] **Soporte para Web Components**: Permitir la inclusión de herramientas interactivas externas de forma segura.
- [ ] **OpenCCB Market**: Galería interna para descargar y habilitar extensiones.
### Fase 36: LTI 1.3 Tool Consumer 🔗
- [ ] **Consumo de herramientas externas**: Capacidad de embeber laboratorios externos (ej: MATLAB, Labster) dentro de OpenCCB.
- [ ] **Delegación de Calificaciones**: Recibir notas de herramientas externas y sincronizarlas con el Gradebook de OpenCCB.
---
## Fase 21: Búsqueda Semántica y RAG Avanzado ✅
- [x] **PGVector Integration**: Implementación de búsqueda semántica con embeddings de 768 dimensiones. (Completado)
- [x] **Semantic Question Search**: Búsqueda por similitud de coseno en question bank. (Completado)
- [x] **Duplicate Detection**: Detección automática de preguntas duplicadas (>95% similitud). (Completado)
- [x] **RAG Mejorado para Generación**: Contexto semántico + verificación de 4 habilidades. (Completado)
- [x] **Knowledge Base Embeddings**: Búsqueda semántica en base de conocimiento para tutor IA. (Completado)
- [x] **Índices IVFFlat**: Optimización para >100k filas (25-100x más rápido). (Completado)
- [x] **MySQL Integration Completa**: Importación de study plans y courses con tracking. (Completado)
- [x] **Test Templates con Filtros**: Filtrado por mysql_course_id, level, course_type. (Completado)
---
**Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos**, **Landing Pages de Cursos (Marketing) automatizadas**, **Diagramas de Mermaid Dinámicos**, **Laboratorios de Código con Hints de IA**, y **Búsqueda Semántica con PGVector**.
**Estado Actual**: Plataforma madura con IA generativa integrada, arquitectura Premium Single-Tenant, búsqueda semántica y monetización operativa.
**Próximas Prioridades**:
1. **Accesibilidad Universal**: Auditoría y ajustes de contraste para cumplimiento WCAG 2.1.
2. **Integraciones Empresariales**: Conectividad con HRIS y ERPs externos.
3. **Optimización de Performance**: Refactorización de componentes críticos y carga diferida (lazy loading).
---
## Fase 22: Finalización de Funcionalidades Pendientes 🛠️
- [ ] **Generación de Certificados**: Implementación de lógica de generación automática al completar curso.
- [ ] Backend: Endpoint para verificar completitud y generar certificado (PDF)
- [ ] Frontend: UI para configurar templates de certificados en Studio
- [ ] Frontend: Botón de descarga en Experience al completar curso
- [ ] Schema de BD ya existe (`certificate_template`), solo falta implementación
- [ ] **Tracking de Progreso Real**: Cálculo y visualización de progreso real del estudiante.
- [ ] Backend: Endpoint para calcular % de completitud basado en lecciones completadas
- [ ] Frontend: Reemplazar hardcoded `progress = 0` en `my-learning/page.tsx`
- [ ] Frontend: Barra de progreso real en catálogo de cursos
- [ ] **Notificaciones de Foros**: Despacho de alertas cuando hay respuestas en hilos suscritos.
- [ ] Backend: Implementar lógica de notificación en `handlers_discussions.rs` (línea 352 tiene TODO)
- [ ] Frontend: Ver que las notificaciones se muestran correctamente en NotificationCenter
- [ ] **Importación Excel para Question Bank**: Fix del código comentado.
- [ ] Backend: Descomentar y implementar `import_from_excel` en `handlers_question_bank.rs`
- [ ] Frontend: Agregar botón de importación Excel en UI de Question Bank
- [ ] Documentación: Formato esperado del archivo Excel
- [ ] **Re-habilitar Rate Limiting**: Solución de incompatibilidad con middleware de auth.
- [ ] Backend: Fix de `GovernorLayer` para que funcione después del middleware de auth
- [ ] Backend: Configurar límites apropiados por tipo de ruta (pública vs protegida)
- [ ] Testing: Verificar que no bloquea peticiones legítimas
---
## Fase 23: Integración de Email/SMTP 📧
- [ ] **Configuración SMTP**: Variables de entorno para configuración de servidor de correo.
- [ ] `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD`, `SMTP_FROM`
- [ ] Soporte para providers: SendGrid, AWS SES, SMTP genérico
- [ ] **Notificaciones por Email**:
- [ ] Recordatorios de deadlines próximos
- [ ] Alertas de respuestas en foros suscritos
- [ ] Notificaciones de nuevas calificaciones
- [ ] Anuncios de curso de instructores
- [ ] **Autenticación por Email**:
- [ ] Password reset vía link de email
- [ ] Verificación de email al registrar cuenta
- [ ] Magic link login (opcional)
- [ ] **Emails Transaccionales**:
- [ ] Welcome email para nuevos usuarios
- [ ] Notificación de inscripción exitosa
- [ ] Certificado de completación por email
- [ ] Recibo de pago de Mercado Pago
- [ ] **Template de Emails**:
- [ ] Templates HTML responsivos con branding personalizado
- [ ] Soporte multi-idioma (EN, ES, PT)
- [ ] Preview de templates en panel de administración
---
## Fase 24: Búsqueda Global 🔍
- [ ] **Search Endpoint Unificado**: API de búsqueda across cursos, lecciones, contenidos.
- [ ] Backend: Endpoint `/search` con filtros por tipo, categoría, instructor
- [ ] Backend: Búsqueda full-text con PostgreSQL (tsvector)
- [ ] Backend: Opcionalmente agregar búsqueda semántica con embeddings (similar a question bank)
- [ ] **UI de Búsqueda**:
- [ ] Frontend: Barra de búsqueda global en navbar de Studio y Experience
- [ ] Frontend: Resultados en tiempo real con autocompletado
- [ ] Frontend: Filtros avanzados (fecha, instructor, tipo de contenido, nivel)
- [ ] **Búsqueda en Contenidos**:
- [ ] Indexación de transcripciones de video para búsqueda
- [ ] Búsqueda en documentos PDF y DOCX
- [ ] Búsqueda en preguntas de quizzes
---
## Fase 25: Soporte SCORM/xAPI 📦
- [ ] **SCORM 1.2/2004 Player**:
- [ ] Backend: Endpoint para subir paquetes SCORM (.zip)
- [ ] Backend: Extracción y almacenamiento de metadatos SCORM
- [ ] Frontend: Player SCORM embebido en Experience
- [ ] Frontend: Preview de paquetes SCORM en Studio
- [ ] **xAPI (Tin Can) Tracking**:
- [ ] Backend: Endpoint para recibir statements xAPI
- [ ] Backend: Almacenamiento de statements en base de datos separada
- [ ] Backend: Endpoint para consultar historial xAPI por usuario/curso
- [ ] Frontend: Dashboard de analíticas xAPI para instructores
- [ ] **Import/Export SCORM**:
- [ ] Backend: Generador de paquetes SCORM desde cursos OpenCCB
- [ ] Backend: Validador de paquetes SCORM importados
- [ ] Frontend: UI para import/export SCORM en Studio
- [ ] **Compatibilidad con Contenidos de Terceros**:
- [ ] Soporte para H5P, Articulate, Adobe Captivate
- [ ] Tracking de progreso y calificaciones desde contenidos SCORM
---
## Fase 26: Accesibilidad WCAG 2.1 ♿
- [ ] **Auditoría de Accesibilidad**:
- [ ] Herramientas: axe-core, Lighthouse, WAVE
- [ ] Reporte de problemas de contraste de color
- [ ] Verificación de navegación por teclado
- [ ] Testing con screen readers (NVDA, VoiceOver, JAWS)
- [ ] **Correcciones de Accesibilidad**:
- [ ] Ajustes de contraste para cumplir WCAG AA (4.5:1 para texto normal)
- [ ] Labels ARIA en todos los componentes interactivos
- [ ] Navegación por teclado completa (Tab, Enter, Escape, flechas)
- [ ] Focus indicators visibles en todos los elementos
- [ ] Skip links para saltar a contenido principal
- [ ] **Accesibilidad de Formularios**:
- [ ] Labels asociados correctamente a inputs
- [ ] Mensajes de error accesibles por screen reader
- [ ] Autocomplete en campos apropiados
- [ ] **Accesibilidad de Multimedia**:
- [ ] Subtítulos obligatorios para videos
- [ ] Transcripciones para contenido de audio
- [ ] Alt text para imágenes importantes
- [ ] **Testing Continuo**:
- [ ] Integración de axe-core en CI/CD
- [ ] Testing manual regular con usuarios de screen readers
- [ ] Documentación de accesibilidad para contribuidores
---
## Fase 27: PWA y Soporte Offline 📱
- [ ] **Progressive Web App (PWA)**:
- [ ] Service worker para caching de assets estáticos
- [ ] Manifest.json para instalación en móviles/desktop
- [ ] Offline fallback page
- [ ] Push notifications para alertas críticas
- [ ] **Descarga de Lecciones**:
- [ ] Frontend: Botón de descarga por lección en Experience
- [ ] Frontend: UI para gestionar descargas (ver/eliminar)
- [ ] Service worker: Caching de contenido de video/audio
- [ ] IndexedDB: Almacenamiento de progreso offline
- [ ] **Sincronización Offline**:
- [ ] Service worker: Queue de acciones offline (calificaciones, notas, progreso)
- [ ] Frontend: Sync automático al reconectar
- [ ] Backend: Endpoint para recibir sync data y reconciliar
- [ ] Manejo de conflictos (última escritura gana, o merge)
- [ ] **Experiencia Offline**:
- [ ] Indicador de estado de conexión en UI
- [ ] Contenido disponible sin conexión claramente marcado
- [ ] Límite de almacenamiento configurable
- [ ] Limpieza automática de caché antiguo
---
## Fase 28: Sistema de Mentoría 🎓
- [ ] **Gestión de Mentores**:
- [ ] Backend: CRUD de asignaciones mentor-estudiante
- [ ] Backend: Endpoints para disponibilidad de mentores
- [ ] Frontend: UI para asignar mentores en panel de administración
- [ ] Frontend: Perfil de mentor con bio, especialidades, disponibilidad
- [ ] **Sesiones 1-a-1**:
- [ ] Backend: Sistema de agendamiento de sesiones
- [ ] Backend: Integración con Jitsi para sesiones virtuales
- [ ] Frontend: Calendario de sesiones para mentores y estudiantes
- [ ] Frontend: Recordatorios por email/notificación
- [ ] **Seguimiento Personalizado**:
- [ ] Backend: Notas de mentor por estudiante
- [ ] Backend: Plan de aprendizaje personalizado por estudiante
- [ ] Frontend: Dashboard de mentor con vista de estudiantes asignados
- [ ] Frontend: Reportes de progreso para mentores
---
## Fase 29: Integraciones Empresariales 🏢
- [ ] **HRIS Connectors**:
- [ ] Integración con Workday (API REST)
- [ ] Integración con SAP SuccessFactors (OData)
- [ ] Integración con BambooHR
- [ ] Sync automático de usuarios, departamentos, managers
- [ ] **LDAP/Active Directory**:
- [ ] Backend: Autenticación vía LDAP
- [ ] Backend: Sync de atributos de usuario desde AD
- [ ] Frontend: Configuración de LDAP en panel de administración
- [ ] Soporte para SSO híbrido (LDAP + OIDC)
- [ ] **Webhooks Salientes**:
- [ ] Backend: Sistema de webhooks configurables por evento
- [ ] Backend: Retry logic con exponential backoff
- [ ] Backend: Dashboard de entrega de webhooks (éxito/fallo)
- [ ] Frontend: UI para gestionar webhooks en Studio
- [ ] Frontend: Test de webhook desde UI
- [ ] **ERP Integrations**:
- [ ] Integración con sistemas de facturación
- [ ] Sync de inscripciones y pagos con ERP
- [ ] Reportes financieros para administradores
---
## Fase 30: Reportes Avanzados y Business Intelligence 📊
- [ ] **Reportes para Estudiantes**:
- [ ] Dashboard de analíticas personales (tiempo de estudio, skills, tendencias)
- [ ] Reporte de progreso semanal/mensual por email
- [ ] Exportación de historial de aprendizaje (PDF, Excel)
- [ ] **Reportes para Instructores**:
- [ ] Reportes automáticos programables (diario, semanal, mensual)
- [ ] Exportación en múltiples formatos (PDF, Excel, CSV)
- [ ] Reportes comparativos entre cohortes
- [ ] Análisis de efectividad de contenido (qué funciona mejor)
- [ ] **Reportes para Administradores**:
- [ ] Dashboard de uso de la plataforma (DAU, WAU, MAU)
- [ ] Análisis de ROI de cursos (costo vs completitud)
- [ ] Reportes de uso de IA (tokens, costo, efectividad)
- [ ] Exportación de datos completos de la plataforma
- [ ] **Business Intelligence**:
- [ ] Integración con herramientas BI externas (Metabase, Tableau)
- [ ] API de datos para dashboards externos
- [ ] Data warehouse schema optimizado para queries analíticos
---
## Fase 31: Mejoras de Seguridad y GDPR 🛡️
- [ ] **Two-Factor Authentication (2FA)**:
- [ ] Backend: Soporte para TOTP (Google Authenticator, Authy)
- [ ] Backend: Backup codes para recuperación
- [ ] Frontend: Setup de 2FA en perfil de usuario
- [ ] Frontend: Login con 2FA
- [ ] **GDPR Compliance**:
- [ ] Backend: Endpoint para exportar todos los datos de un usuario
- [ ] Backend: Endpoint para eliminar todos los datos de un usuario (right to be forgotten)
- [ ] Frontend: UI para solicitar exportación/eliminación
- [ ] Frontend: Consent management para cookies y tracking
- [ ] **Audit Logs Mejorados**:
- [ ] Backend: Exportación de audit logs (CSV, JSON)
- [ ] Backend: Alertas de actividad sospechosa
- [ ] Frontend: Filtros avanzados de audit logs
- [ ] Frontend: Dashboard de seguridad
- [ ] **Mejoras de Seguridad**:
- [ ] CSRF protection en todos los endpoints
- [ ] Content Security Policy headers
- [ ] Rate limiting por IP y por usuario
- [ ] IP allowlisting para admin endpoints
---
**Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos**, **Landing Pages de Cursos (Marketing) automatizadas**, **Diagramas de Mermaid Dinámicos**, **Laboratorios de Código con Hints de IA**, y **Búsqueda Semántica con PGVector**.
**Próximas Prioridades**:
1. **Finalización de Funcionalidades Pendientes**: Certificados, progreso real, notificaciones de foros, importación Excel, rate limiting.
2. **Integración de Email/SMTP**: Notificaciones por email, password reset, emails transaccionales.
3. **Accesibilidad Universal**: Auditoría y ajustes de contraste para cumplimiento WCAG 2.1.
4. **Búsqueda Global**: Search unificado en cursos, lecciones y contenidos.
5. **Integraciones Empresariales**: Conectividad con HRIS, LDAP/Active Directory, webhooks salientes.
6. **PWA y Offline**: Service workers, descarga de lecciones, sync offline.
7. **Seguridad**: 2FA, GDPR compliance, rate limiting re-habilitado.
1. Finalización de **Certificados y Progreso Real**.
2. Despliegue de **Infraestructura SMTP** para comunicación global.
3. Auditoría de **Accesibilidad Universal (WCAG)**.
4. Implementación de **IA de Moderación (Seguridad)**.
+7
View File
@@ -2779,6 +2779,13 @@ pub async fn register(
State(pool): State<PgPool>,
Json(payload): Json<AuthPayload>,
) -> Result<Json<AuthResponse>, (StatusCode, String)> {
if payload.email.trim().is_empty() || payload.password.trim().is_empty() {
return Err((
StatusCode::BAD_REQUEST,
"El email y la contraseña son obligatorios".into(),
));
}
let password_hash = hash(payload.password, DEFAULT_COST)
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Hashing failed".into()))?;
@@ -98,7 +98,9 @@ async fn upsert_organization_exercise_settings(
organization_id: Uuid,
payload: &UpdateOrganizationExerciseSettingsPayload,
) -> Result<OrganizationExerciseSettings, sqlx::Error> {
sqlx::query_as::<_, OrganizationExerciseSettings>(
let mut tx = pool.begin().await?;
let settings = sqlx::query_as::<_, OrganizationExerciseSettings>(
r#"
INSERT INTO organization_exercise_settings (
organization_id,
@@ -144,8 +146,21 @@ async fn upsert_organization_exercise_settings(
.bind(payload.mermaid_enabled)
.bind(payload.code_lab_enabled)
.bind(payload.certificates_enabled)
.fetch_one(pool)
.await
.fetch_one(&mut *tx)
.await?;
// Sincronizar con la tabla organizations para que el LMS reciba el valor correcto al publicar
sqlx::query(
"UPDATE organizations SET certificates_enabled = $1, updated_at = NOW() WHERE id = $2"
)
.bind(payload.certificates_enabled)
.bind(organization_id)
.execute(&mut *tx)
.await?;
tx.commit().await?;
Ok(settings)
}
pub async fn get_organization_exercise_settings(
+6 -6
View File
@@ -60,8 +60,8 @@ pub async fn sync_sam_students(
State(pool): State<PgPool>,
) -> Result<Json<SamSyncResponse>, (StatusCode, String)> {
// Conectar a la base de datos externa de SAM
let sam_url = std::env::var("SAM_DATABASE_URL")
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DATABASE_URL no configurada".to_string()))?;
let sam_url = std::env::var("SAM_DIAGNOSTICO_DATABASE_URL")
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DIAGNOSTICO_DATABASE_URL no configurada".to_string()))?;
let sam_pool = sqlx::PgPool::connect(&sam_url)
.await
@@ -191,8 +191,8 @@ pub async fn sync_sam_assignments(
State(pool): State<PgPool>,
) -> Result<Json<SamSyncResponse>, (StatusCode, String)> {
// Conectar a la base de datos externa de SAM
let sam_url = std::env::var("SAM_DATABASE_URL")
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DATABASE_URL no configurada".to_string()))?;
let sam_url = std::env::var("SAM_DIAGNOSTICO_DATABASE_URL")
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DIAGNOSTICO_DATABASE_URL no configurada".to_string()))?;
let sam_pool = sqlx::PgPool::connect(&sam_url)
.await
@@ -382,8 +382,8 @@ pub async fn sync_all_sam(
let mut assignments_synced = 0;
// Conectar a la base de datos externa de SAM
let sam_url = std::env::var("SAM_DATABASE_URL")
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DATABASE_URL no configurada".to_string()))?;
let sam_url = std::env::var("SAM_DIAGNOSTICO_DATABASE_URL")
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "SAM_DIAGNOSTICO_DATABASE_URL no configurada".to_string()))?;
let sam_pool = sqlx::PgPool::connect(&sam_url)
.await
+14 -3
View File
@@ -161,8 +161,16 @@ async fn main() {
])
.expose_headers([header::CONTENT_LENGTH, header::CONTENT_TYPE, header::CONTENT_RANGE, header::ACCEPT_RANGES]);
// Rate limiting: Deshabilitado temporalmente por problemas de compatibilidad con tower-governor
// Para habilitar en producción, configurar con GovernorLayer y ajustar los límites apropiadamente
use tower_governor::{GovernorConfigBuilder, GovernorLayer};
use std::sync::Arc;
let governor_conf = Arc::new(
GovernorConfigBuilder::default()
.per_second(5) // CMS usually has more complex operations, slightly lower limit
.burst_size(20)
.finish()
.unwrap(),
);
// Rutas protegidas que requieren autenticación y contexto de organización
let protected_routes = Router::new()
@@ -500,7 +508,10 @@ async fn main() {
)
.route_layer(middleware::from_fn(
common::middleware::org_extractor_middleware,
));
))
.route_layer(GovernorLayer {
config: governor_conf,
});
let api_routes = Router::new()
.route(
@@ -0,0 +1,59 @@
-- Migration: Automatic Enrollment Progress Update via Trigger
-- Created: 2026-04-14
-- 1. Function to recalculate course progress for a student
CREATE OR REPLACE FUNCTION fn_recalculate_enrollment_progress()
RETURNS TRIGGER AS $$
DECLARE
v_total_lessons INTEGER;
v_completed_lessons INTEGER;
v_progress FLOAT4;
BEGIN
-- Get total number of lessons in the course
-- We use the course_id from the new grade entry
SELECT COUNT(*) INTO v_total_lessons
FROM lessons
WHERE module_id IN (SELECT id FROM modules WHERE course_id = NEW.course_id);
-- Get number of distinct lessons with a grade for this user in this course
SELECT COUNT(DISTINCT lesson_id) INTO v_completed_lessons
FROM user_grades
WHERE user_id = NEW.user_id AND course_id = NEW.course_id;
-- Calculate progress percentage
IF v_total_lessons > 0 THEN
v_progress := (v_completed_lessons::FLOAT4 / v_total_lessons::FLOAT4) * 100;
ELSE
v_progress := 0;
END IF;
-- Update the enrollments table for this specific user and course
UPDATE enrollments
SET progress = v_progress
WHERE user_id = NEW.user_id AND course_id = NEW.course_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 2. Trigger to execute the function after any activity is graded
DROP TRIGGER IF EXISTS tr_update_enrollment_progress ON user_grades;
CREATE TRIGGER tr_update_enrollment_progress
AFTER INSERT OR UPDATE ON user_grades
FOR EACH ROW
EXECUTE FUNCTION fn_recalculate_enrollment_progress();
-- 3. Initial sync: Update progress for all existing enrollments
UPDATE enrollments e
SET progress = COALESCE(
(
SELECT (COUNT(DISTINCT ug.lesson_id)::FLOAT4 / NULLIF((
SELECT COUNT(*)
FROM lessons l
WHERE l.module_id IN (SELECT id FROM modules m WHERE m.course_id = e.course_id)
), 0)::FLOAT4) * 100
FROM user_grades ug
WHERE ug.user_id = e.user_id AND ug.course_id = e.course_id
),
0
);
+14 -10
View File
@@ -119,15 +119,16 @@ async fn main() {
])
.expose_headers([header::CONTENT_LENGTH, header::CONTENT_TYPE]);
// Rate limiter DESHABILITADO debido a problemas de compatibilidad con el middleware de autenticación
// Ver QWEN.md para más detalles
// let governor_conf = Arc::new(
// GovernorConfigBuilder::default()
// .per_second(10)
// .burst_size(50)
// .finish()
// .unwrap(),
// );
use tower_governor::{GovernorConfigBuilder, GovernorLayer};
use std::sync::Arc;
let governor_conf = Arc::new(
GovernorConfigBuilder::default()
.per_second(10)
.burst_size(50)
.finish()
.unwrap(),
);
// Rate limiter solo para rutas protegidas (después del middleware de autenticación)
let protected_routes = Router::new()
@@ -343,7 +344,10 @@ async fn main() {
)
.route_layer(middleware::from_fn(
common::middleware::org_extractor_middleware,
));
))
.route_layer(GovernorLayer {
config: governor_conf,
});
let public_routes = Router::new()
.route("/api-docs/openapi.json", get(|| async {
+1
View File
@@ -188,6 +188,7 @@ pub struct Enrollment {
pub organization_id: Uuid,
pub course_id: Uuid,
pub external_id: Option<i32>, // idDetalleContrato del sistema externo
pub progress: f32,
pub enrolled_at: DateTime<Utc>,
}
+69 -3
View File
@@ -9,6 +9,8 @@ import { useAuth } from "@/context/AuthContext";
import DiscussionBoard from "@/components/DiscussionBoard";
import { AnnouncementsList } from "@/components/AnnouncementsList";
import AboutCourse from "@/components/AboutCourse";
import CertificateModal from "@/components/CertificateModal";
import { CertificateResponse } from "@/lib/api";
export default function CourseOutlinePage({ params }: { params: { id: string } }) {
const { user } = useAuth();
@@ -22,6 +24,11 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
const [instructors, setInstructors] = useState<any[]>([]);
const [meetings, setMeetings] = useState<Meeting[]>([]);
const [activeTab, setActiveTab] = useState<'outline' | 'about'>('outline');
const [progress, setProgress] = useState(0);
const [certificate, setCertificate] = useState<CertificateResponse | null>(null);
const [showCertificateModal, setShowCertificateModal] = useState(false);
const [loadingCertificate, setLoadingCertificate] = useState(false);
const [orgSettings, setOrgSettings] = useState<any>(null);
useEffect(() => {
const fetchData = async () => {
@@ -37,11 +44,15 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
setUserGrades(grades);
const enrollmentData = await lmsApi.getEnrollments(user.id);
const enrolled = enrollmentData.some(e => e.course_id === params.id);
const enrollment = enrollmentData.find(e => e.course_id === params.id);
// Allow preview token to override enrollment status
const isPreview = typeof window !== 'undefined' && !!sessionStorage.getItem('preview_token');
setIsEnrolled(enrolled || isPreview);
setIsEnrolled(!!enrollment || isPreview);
if (enrollment) {
setProgress(enrollment.progress * 100);
}
} else {
// Even if not logged in, if there's a preview token, consider "enrolled" for UI
const isPreview = typeof window !== 'undefined' && !!sessionStorage.getItem('preview_token');
@@ -65,6 +76,11 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
lmsApi.getMeetings(params.id)
.then(setMeetings)
.catch(console.error);
// Load organization settings (branding includes the certificates_enabled flag)
lmsApi.getBranding()
.then(res => setOrgSettings(res.organization))
.catch(console.error);
}, [params.id, user]);
const handleEnrollOrBuy = async () => {
@@ -120,6 +136,38 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
});
};
const handleViewCertificate = async () => {
if (certificate) {
setShowCertificateModal(true);
return;
}
setLoadingCertificate(true);
try {
const data = await lmsApi.getCertificate(params.id);
setCertificate(data);
setShowCertificateModal(true);
} catch (error: any) {
console.error("No se pudo obtener el certificado", error);
if (error.status === 404 || error.status === 403) {
// Try to issue it if completed but not issued
if (progress >= 100) {
try {
const issued = await lmsApi.issueCertificate(params.id);
setCertificate(issued);
setShowCertificateModal(true);
} catch (issueError) {
alert("No se pudo generar el certificado. Asegúrate de haber aprobado todas las lecciones.");
}
} else {
alert("Aún no has completado este curso.");
}
}
} finally {
setLoadingCertificate(false);
}
};
const getStatusIcon = (lessonId: string, isGraded: boolean, allowRetry: boolean) => {
if (isLessonLocked(lessonId)) {
return <Lock size={18} className="text-gray-600" />;
@@ -274,6 +322,17 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
📊 Progreso
</button>
</Link>
{isEnrolled && orgSettings?.certificates_enabled !== false && progress >= 100 && (
<button
onClick={handleViewCertificate}
disabled={loadingCertificate}
className="btn-premium px-8 py-3 !bg-emerald-600 !text-white shadow-lg shadow-emerald-500/20 active:scale-95 flex items-center gap-2"
>
<Award size={16} />
{loadingCertificate ? "Preparando..." : "Mi Certificado"}
</button>
)}
</div>
</div>
@@ -485,6 +544,13 @@ export default function CourseOutlinePage({ params }: { params: { id: string } }
</div>
)}
</div>
{showCertificateModal && certificate && (
<CertificateModal
certificate={certificate}
onClose={() => setShowCertificateModal(false)}
/>
)}
</div>
);
}
+1 -3
View File
@@ -40,9 +40,7 @@ export default function MyLearningPage() {
try {
const { course, modules } = await lmsApi.getCourseOutline(enrollment.course_id);
// TODO: Implement actual progress tracking
// For now, show 0% progress for all courses
const progress = 0;
const progress = enrollment.progress || 0;
enrichedEnrollments.push({
course: { ...course, modules },
@@ -0,0 +1,98 @@
"use client";
import { X, Printer, Download, Award, ShieldCheck } from "lucide-react";
import { CertificateResponse } from "@/lib/api";
interface CertificateModalProps {
certificate: CertificateResponse;
onClose: () => void;
}
export default function CertificateModal({ certificate, onClose }: CertificateModalProps) {
const handlePrint = () => {
window.print();
};
return (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/80 backdrop-blur-md animate-in fade-in duration-300">
<div className="relative w-full max-w-5xl md:h-[90vh] bg-white dark:bg-slate-900 rounded-[2rem] overflow-hidden flex flex-col shadow-2xl border border-white/10">
{/* Header / Toolbar */}
<div className="flex items-center justify-between p-6 border-b border-slate-100 dark:border-white/5 bg-slate-50 dark:bg-black/20 no-print">
<div className="flex items-center gap-4">
<div className="w-10 h-10 rounded-xl bg-blue-600 flex items-center justify-center text-white shadow-lg shadow-blue-500/20">
<Award size={20} />
</div>
<div>
<h2 className="text-sm font-bold text-slate-900 dark:text-white">Certificado Oficial</h2>
<p className="text-[10px] font-black uppercase tracking-widest text-blue-600 dark:text-blue-500">Emitido el {new Date(certificate.issued_at).toLocaleDateString()}</p>
</div>
</div>
<div className="flex items-center gap-2">
<button
onClick={handlePrint}
className="p-3 rounded-xl hover:bg-slate-200 dark:hover:bg-white/10 text-slate-600 dark:text-gray-400 transition-all flex items-center gap-2 text-xs font-bold"
>
<Printer size={18} />
<span className="hidden sm:inline">Imprimir / PDF</span>
</button>
<button
onClick={onClose}
className="p-3 rounded-xl hover:bg-red-500/10 text-slate-400 hover:text-red-500 transition-all"
>
<X size={20} />
</button>
</div>
</div>
{/* Certificate Content Wrapper */}
<div className="flex-1 overflow-y-auto p-4 md:p-12 flex items-center justify-center bg-slate-100 dark:bg-black/40">
<div className="certificate-container shadow-2xl ring-1 ring-black/5">
{/*
We inject the HTML directly.
Note: The backend must sanitize this OR we trust our own generated template.
*/}
<div
className="bg-white"
dangerouslySetInnerHTML={{ __html: certificate.certificate_html }}
/>
</div>
</div>
{/* Footer Info */}
<div className="p-6 bg-slate-50 dark:bg-black/20 border-t border-slate-100 dark:border-white/5 flex flex-col md:flex-row items-center justify-between gap-4 no-print">
<div className="flex items-center gap-3 text-emerald-600 dark:text-emerald-500">
<ShieldCheck size={18} />
<span className="text-[10px] font-black uppercase tracking-widest">Este certificado es auténtico y verificable</span>
</div>
<div className="text-[10px] font-bold text-slate-400 dark:text-gray-500 flex items-center gap-2">
Código: <code className="bg-slate-200 dark:bg-white/5 px-2 py-1 rounded text-blue-600 dark:text-blue-400 font-mono">{certificate.verification_code}</code>
</div>
</div>
<style jsx global>{`
.certificate-container {
width: 100%;
max-width: 800px;
background: white;
transform-origin: center;
}
@media print {
.no-print { display: none !important; }
body { background: white !important; margin: 0 !important; padding: 0 !important; }
.certificate-container {
box-shadow: none !important;
ring: none !important;
width: 100% !important;
max-width: none !important;
position: absolute;
top: 0;
left: 0;
}
}
`}</style>
</div>
</div>
);
}
+39
View File
@@ -142,6 +142,30 @@ export interface PaymentPreferenceResponse {
init_point: string;
}
export interface CertificateResponse {
id: string;
user_id: string;
course_id: string;
course_title: string;
student_name: string;
certificate_html: string;
issued_at: string;
verification_code: string;
metadata: any;
}
export interface CertificateResponse {
id: string;
user_id: string;
course_id: string;
course_title: string;
student_name: string;
certificate_html: string;
issued_at: string;
verification_code: string;
metadata: any;
}
export interface QuizQuestion {
id: string;
question: string;
@@ -371,6 +395,7 @@ export interface Enrollment {
id: string;
user_id: string;
course_id: string;
progress: number;
enrolled_at: string;
}
@@ -862,5 +887,19 @@ export const lmsApi = {
async getMyBadges(): Promise<Badge[]> {
return apiFetch(`/my/badges`, {}, false);
},
// Certificates
async getCertificate(courseId: string): Promise<CertificateResponse> {
return apiFetch(`/courses/${courseId}/certificate`);
},
async issueCertificate(courseId: string, forceReissue = false): Promise<CertificateResponse> {
return apiFetch(`/courses/${courseId}/certificate/issue`, {
method: 'POST',
body: JSON.stringify({ force_reissue: forceReissue })
});
},
async verifyCertificate(code: string): Promise<any> {
return apiFetch(`/certificates/verify/${code}`);
}
};
@@ -0,0 +1,154 @@
"use client";
import React, { useState } from "react";
import { cmsApi } from "@/lib/api";
import { RefreshCw, Database, Users, CheckCircle2, AlertCircle, Loader2 } from "lucide-react";
interface IntegrationsSectionProps {
courseId: string;
}
export default function IntegrationsSection({ courseId }: IntegrationsSectionProps) {
const [syncingAll, setSyncingAll] = useState(false);
const [syncingStudents, setSyncingStudents] = useState(false);
const [syncingAssignments, setSyncingAssignments] = useState(false);
const [status, setStatus] = useState<{ type: 'success' | 'error', message: string } | null>(null);
const handleSyncAll = async () => {
setSyncingAll(true);
setStatus(null);
try {
const result = await cmsApi.syncSamAll();
setStatus({
type: 'success',
message: `Sincronización completa finalizada. Estudiantes: ${result.students_synced}, Asignaciones: ${result.assignments_synced}`
});
} catch (err: any) {
setStatus({ type: 'error', message: err.message || "Error al sincronizar con SAM" });
} finally {
setSyncingAll(false);
}
};
const handleSyncStudents = async () => {
setSyncingStudents(true);
setStatus(null);
try {
const result = await cmsApi.syncSamStudents();
setStatus({
type: 'success',
message: `Estudiantes sincronizados: ${result.students_synced}`
});
} catch (err: any) {
setStatus({ type: 'error', message: err.message || "Error al sincronizar estudiantes" });
} finally {
setSyncingStudents(false);
}
};
const handleSyncAssignments = async () => {
setSyncingAssignments(true);
setStatus(null);
try {
const result = await cmsApi.syncSamAssignments();
setStatus({
type: 'success',
message: `Asignaciones sincronizadas: ${result.assignments_synced}`
});
} catch (err: any) {
setStatus({ type: 'error', message: err.message || "Error al sincronizar asignaciones" });
} finally {
setSyncingAssignments(false);
}
};
return (
<section className="bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-3xl p-8 space-y-8 shadow-sm">
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-2xl bg-indigo-600/10 flex items-center justify-center text-indigo-600 dark:text-indigo-400">
<RefreshCw size={24} />
</div>
<div>
<h2 className="section-title">Integraciones y Sincronización</h2>
<p className="text-sm text-slate-500 dark:text-gray-400">Gestiona la conexión con sistemas externos (SAM y MySQL Legacy)</p>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* SAM Integration Card */}
<div className="bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-2xl p-6 shadow-sm space-y-6">
<div className="flex items-center gap-2 text-indigo-600 dark:text-indigo-400">
<Database size={20} />
<h3 className="font-bold uppercase tracking-wider text-sm">SAM (Sistema Académico)</h3>
</div>
<p className="text-xs text-slate-500 dark:text-gray-400">
Sincroniza la base de datos de estudiantes y las inscripciones a cursos desde el sistema SAM v3.
</p>
<div className="space-y-3">
<button
onClick={handleSyncAll}
disabled={syncingAll || syncingStudents || syncingAssignments}
className="w-full flex items-center justify-between p-4 bg-slate-50 dark:bg-black/20 hover:bg-indigo-50 dark:hover:bg-indigo-500/10 border border-slate-200 dark:border-white/10 rounded-xl transition-all group"
>
<div className="flex items-center gap-3">
<RefreshCw className={`w-5 h-5 text-indigo-500 ${syncingAll ? 'animate-spin' : 'group-hover:rotate-180 transition-transform duration-500'}`} />
<div className="text-left">
<div className="text-sm font-bold text-slate-900 dark:text-white">Sincronización Total</div>
<div className="text-[10px] text-slate-500 dark:text-gray-500">Estudiantes + Inscripciones</div>
</div>
</div>
</button>
<div className="flex gap-3">
<button
onClick={handleSyncStudents}
disabled={syncingAll || syncingStudents}
className="flex-1 flex items-center gap-2 p-3 bg-white dark:bg-black/10 hover:bg-slate-50 dark:hover:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl text-xs font-bold text-slate-600 dark:text-gray-300 transition-all"
>
<Users size={14} />
{syncingStudents ? "Sincronizando..." : "Solo Estudiantes"}
</button>
<button
onClick={handleSyncAssignments}
disabled={syncingAll || syncingAssignments}
className="flex-1 flex items-center gap-2 p-3 bg-white dark:bg-black/10 hover:bg-slate-50 dark:hover:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl text-xs font-bold text-slate-600 dark:text-gray-300 transition-all"
>
<RefreshCw size={14} className={syncingAssignments ? 'animate-spin' : ''} />
{syncingAssignments ? "Sincronizando..." : "Solo Inscripciones"}
</button>
</div>
</div>
</div>
{/* MySQL Legacy Sync Card */}
<div className="bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-2xl p-6 shadow-sm space-y-6 opacity-75 grayscale hover:grayscale-0 hover:opacity-100 transition-all">
<div className="flex items-center gap-2 text-slate-600 dark:text-gray-400">
<AlertCircle size={20} />
<h3 className="font-bold uppercase tracking-wider text-sm">MySQL Legacy Sync</h3>
</div>
<p className="text-xs text-slate-500 dark:text-gray-400">
Importación manual de contenidos y estructuras de cursos desde el sistema antiguo.
<span className="block mt-1 text-amber-500 font-bold"> Use con precaución: puede duplicar contenidos.</span>
</p>
<button
disabled={true}
className="w-full flex items-center justify-center p-4 bg-slate-100 dark:bg-black/40 border border-dashed border-slate-300 dark:border-white/10 rounded-xl text-slate-400 text-xs font-bold"
>
Próximamente para este curso específico
</button>
</div>
</div>
{status && (
<div className={`p-4 rounded-2xl flex items-center gap-3 animate-in fade-in slide-in-from-bottom-2 ${status.type === 'success' ? 'bg-green-500/10 text-green-600 dark:text-green-400 border border-green-500/20' : 'bg-red-500/10 text-red-600 dark:text-red-400 border border-red-500/20'}`}>
{status.type === 'success' ? <CheckCircle2 size={20} /> : <AlertCircle size={20} />}
<p className="text-sm font-bold">{status.message}</p>
</div>
)}
</section>
);
}
@@ -22,6 +22,7 @@ const DEFAULT_CERTIFICATE_TEMPLATE = `
import CourseEditorLayout from "@/components/CourseEditorLayout";
import TeamManagementSection from "./TeamManagementSection";
import IntegrationsSection from "./IntegrationsSection";
export default function CourseSettingsPage() {
const { id } = useParams() as { id: string };
@@ -147,6 +148,7 @@ export default function CourseSettingsPage() {
>
<div className="space-y-8">
<TeamManagementSection courseId={id} />
<IntegrationsSection courseId={id} />
{/* Passing Percentage Section */}
<section className="bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-3xl p-8 shadow-sm">
@@ -43,6 +43,11 @@ const featureCards: Array<{
title: "Code Lab",
description: "Permite laboratorios de código generados o editados manualmente.",
},
{
key: "certificates_enabled",
title: "Generación de Certificados",
description: "Habilita la emisión automática de certificados al completar cursos.",
},
];
const defaultSettings: OrganizationExerciseSettings = {
@@ -54,6 +59,7 @@ const defaultSettings: OrganizationExerciseSettings = {
role_playing_enabled: true,
mermaid_enabled: false,
code_lab_enabled: true,
certificates_enabled: true,
};
export default function ExerciseFeatureSettings() {
@@ -94,6 +100,7 @@ export default function ExerciseFeatureSettings() {
role_playing_enabled: settings.role_playing_enabled,
mermaid_enabled: settings.mermaid_enabled,
code_lab_enabled: settings.code_lab_enabled,
certificates_enabled: settings.certificates_enabled,
};
const updated = await cmsApi.updateOrganizationExerciseSettings(payload);
setSettings(updated);
+12
View File
@@ -278,6 +278,7 @@ export interface OrganizationExerciseSettings {
role_playing_enabled: boolean;
mermaid_enabled: boolean;
code_lab_enabled: boolean;
certificates_enabled: boolean;
}
export interface User {
@@ -433,6 +434,12 @@ export interface GlobalAiUsageResponse {
student_chat_usage: StudentChatUsage[];
}
export interface SamSyncResponse {
students_synced: number;
assignments_synced: number;
errors: string[];
}
// ==================== Grading ====================
export interface GradingCategory {
@@ -899,6 +906,11 @@ export const cmsApi = {
getCourseTeam: (courseId: string): Promise<CourseInstructor[]> => apiFetch(`/courses/${courseId}/team`),
addTeamMember: (courseId: string, email: string, role: string): Promise<CourseInstructor> => apiFetch(`/courses/${courseId}/team`, { method: 'POST', body: JSON.stringify({ email, role }) }),
removeTeamMember: (courseId: string, userId: string): Promise<void> => apiFetch(`/courses/${courseId}/team/${userId}`, { method: 'DELETE' }),
// SAM Integration
syncSamStudents: (): Promise<SamSyncResponse> => apiFetch('/sam/sync-students', { method: 'POST' }),
syncSamAssignments: (): Promise<SamSyncResponse> => apiFetch('/sam/sync-assignments', { method: 'POST' }),
syncSamAll: (): Promise<SamSyncResponse> => apiFetch('/sam/sync-all', { method: 'POST' }),
getUsers: (): Promise<User[]> => apiFetch('/users'),
// Modules & Lessons