feat: fixing certificate and block
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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)**.
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
);
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>,
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user