feat: completar fases 3 y 4 del roadmap mvp (gradebook, drag-and-drop, impersonacion) y actualizar README

This commit is contained in:
2026-09-23 12:10:31 -03:00
parent 4ebc5df4fd
commit 7ad4e3f099
38 changed files with 3804 additions and 390 deletions
+25 -16
View File
@@ -14,13 +14,13 @@
{% block content %}
{% if user.is_authenticated %}
<div class="container-fluid pt-5 mt-4">
<div class="container-fluid px-0">
{% endif %}
<!-- ========================================================================= -->
<!-- 1. HEADER & ROLE PERSPECTIVE SWITCHER -->
<!-- ========================================================================= -->
<div class="dashboard-role-banner mb-4 shadow-sm">
<div class="dashboard-role-banner mb-3 shadow-sm">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-3">
<div>
<div class="d-flex align-items-center gap-2 mb-1 flex-wrap">
@@ -252,12 +252,12 @@
</span>
</div>
<div class="progress mb-3" style="height: 14px;">
<div class="progress-bar bg-success progress-bar-striped" role="progressbar" style="width: {{ stats.assigned_classrooms_pct }}%;"
<div class="progress-bar bg-success progress-bar-striped" role="progressbar" {{ ('style="width: ' ~ (stats.assigned_classrooms_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.assigned_classrooms_pct }}" aria-valuemin="0" aria-valuemax="100"
title="Asignadas: {{ stats.assigned_classrooms }} ({{ stats.assigned_classrooms_pct }}%)">
{{ stats.assigned_classrooms_pct }}%
</div>
<div class="progress-bar bg-warning" role="progressbar" style="width: {{ stats.unassigned_classrooms_pct }}%;"
<div class="progress-bar bg-warning" role="progressbar" {{ ('style="width: ' ~ (stats.unassigned_classrooms_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.unassigned_classrooms_pct }}" aria-valuemin="0" aria-valuemax="100"
title="Sin Asignar: {{ stats.unassigned_classrooms }} ({{ stats.unassigned_classrooms_pct }}%)">
{{ stats.unassigned_classrooms_pct }}%
@@ -274,11 +274,11 @@
</span>
</div>
<div class="progress" style="height: 10px;">
<div class="progress-bar bg-info" role="progressbar" style="width: {{ stats.assigned_today_pct }}%;"
<div class="progress-bar bg-info" role="progressbar" {{ ('style="width: ' ~ (stats.assigned_today_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.assigned_today_pct }}" aria-valuemin="0" aria-valuemax="100"
title="En uso hoy: {{ stats.assigned_today_classrooms }}">
</div>
<div class="progress-bar bg-secondary-subtle" role="progressbar" style="width: {{ stats.unassigned_today_pct }}%;"
<div class="progress-bar bg-secondary-subtle" role="progressbar" {{ ('style="width: ' ~ (stats.unassigned_today_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.unassigned_today_pct }}" aria-valuemin="0" aria-valuemax="100"
title="Libres hoy: {{ stats.unassigned_today_classrooms }}">
</div>
@@ -596,12 +596,12 @@
</span>
</div>
<div class="progress mb-3" style="height: 14px;">
<div class="progress-bar bg-success progress-bar-striped" role="progressbar" style="width: {{ stats.assigned_classrooms_pct }}%;"
<div class="progress-bar bg-success progress-bar-striped" role="progressbar" {{ ('style="width: ' ~ (stats.assigned_classrooms_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.assigned_classrooms_pct }}" aria-valuemin="0" aria-valuemax="100"
title="Asignadas: {{ stats.assigned_classrooms }} ({{ stats.assigned_classrooms_pct }}%)">
{{ stats.assigned_classrooms_pct }}%
</div>
<div class="progress-bar bg-warning" role="progressbar" style="width: {{ stats.unassigned_classrooms_pct }}%;"
<div class="progress-bar bg-warning" role="progressbar" {{ ('style="width: ' ~ (stats.unassigned_classrooms_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.unassigned_classrooms_pct }}" aria-valuemin="0" aria-valuemax="100"
title="Sin Asignar: {{ stats.unassigned_classrooms }} ({{ stats.unassigned_classrooms_pct }}%)">
{{ stats.unassigned_classrooms_pct }}%
@@ -618,11 +618,11 @@
</span>
</div>
<div class="progress" style="height: 10px;">
<div class="progress-bar bg-info" role="progressbar" style="width: {{ stats.assigned_today_pct }}%;"
<div class="progress-bar bg-info" role="progressbar" {{ ('style="width: ' ~ (stats.assigned_today_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.assigned_today_pct }}" aria-valuemin="0" aria-valuemax="100"
title="En uso hoy: {{ stats.assigned_today_classrooms }}">
</div>
<div class="progress-bar bg-secondary-subtle" role="progressbar" style="width: {{ stats.unassigned_today_pct }}%;"
<div class="progress-bar bg-secondary-subtle" role="progressbar" {{ ('style="width: ' ~ (stats.unassigned_today_pct or 0) ~ '%;"') | safe }}
aria-valuenow="{{ stats.unassigned_today_pct }}" aria-valuemin="0" aria-valuemax="100"
title="Libres hoy: {{ stats.unassigned_today_classrooms }}">
</div>
@@ -1346,14 +1346,14 @@
</a>
</div>
<div class="col-md-6 col-lg-3">
<a href="/classrooms/list_classrooms" class="card h-100 p-3 action-menu-card bg-body">
<a href="/schedule/my_grades" class="card h-100 p-3 action-menu-card bg-body">
<div class="d-flex align-items-center">
<div class="quick-icon-circle bg-warning-subtle text-warning me-3">
<i class="bi bi-buildings fs-4"></i>
<i class="bi bi-journal-check fs-4"></i>
</div>
<div>
<h6 class="mb-1 fw-bold text-body">Espacios del Campus</h6>
<p class="text-muted small mb-0">Sedes, edificios y planos</p>
<h6 class="mb-1 fw-bold text-body">Mis Calificaciones</h6>
<p class="text-muted small mb-0">Notas, regularidad y actas</p>
</div>
</div>
</a>
@@ -1375,7 +1375,7 @@
<table class="table table-hover align-middle mb-0">
<thead class="table-light small">
<tr>
<th class="ps-3">Fecha</th>
<th class="ps-3">Fecha & Cuenta Regresiva</th>
<th>Tipo de Hito</th>
<th>Materia / Código</th>
<th>Aula / Enlace</th>
@@ -1386,7 +1386,16 @@
{% for m in role_data.upcoming_milestones %}
<tr>
<td class="ps-3 font-monospace fw-bold text-primary">
{{ m.date }}
<div>{{ m.date }}</div>
{% if m.days_remaining is not none and m.days_remaining is defined %}
{% if m.days_remaining == 0 %}
<span class="badge bg-danger text-white small">¡Hoy!</span>
{% elif m.days_remaining == 1 %}
<span class="badge bg-warning text-dark small">¡Mañana!</span>
{% elif m.days_remaining > 1 %}
<span class="badge bg-info-subtle text-info border small">Faltan {{ m.days_remaining }} días</span>
{% endif %}
{% endif %}
</td>
<td>
<span class="badge" data-color="{{ m.type_obj.color if m.type_obj else '#0d6efd' }}" style="background-color:var(--badge-bg,#0d6efd);color:#fff;">