fix(classrooms): blindar vistas presenciales y virtuales sin aulas + feat(admin): reinicializacion de sistema con clave de admin
This commit is contained in:
@@ -88,6 +88,11 @@
|
||||
<i class="bi bi-window-desktop me-2 text-primary"></i>Interfaz & Dashboard
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link text-danger" id="tab-maintenance-btn" data-bs-toggle="tab" data-bs-target="#tab-maintenance" type="button" role="tab">
|
||||
<i class="bi bi-radioactive me-2 text-danger"></i>Mantenimiento & Reinicio
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -549,6 +554,93 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========================================== -->
|
||||
<!-- PESTAÑA 5: MANTENIMIENTO & REINICIO -->
|
||||
<!-- ========================================== -->
|
||||
<div class="tab-pane fade" id="tab-maintenance" role="tabpanel">
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-8">
|
||||
<!-- Danger Zone Card -->
|
||||
<div class="card border border-danger shadow-sm rounded-3 overflow-hidden">
|
||||
<div class="card-header bg-danger text-white py-3">
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="bi bi-exclamation-triangle-fill fs-4 me-2"></i>
|
||||
<div>
|
||||
<h5 class="h6 fw-bold mb-0 text-white">Zona de Peligro: Reinicialización Total del Sistema</h5>
|
||||
<small class="text-white-50">Depuración integral de datos operacionales para inicio de ciclo o migración en limpio</small>
|
||||
</div>
|
||||
</div>
|
||||
<span class="badge bg-white text-danger font-monospace px-2 py-1 small">Requiere Clave Admin</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-4 bg-body">
|
||||
<p class="mb-3 text-body">
|
||||
Esta herramienta permite vaciar completamente los datos operacionales generados por la actividad académica y de uso diario en la plataforma, restableciendo el sistema a su estado inicial.
|
||||
</p>
|
||||
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<div class="p-3 rounded-3 bg-danger-subtle border border-danger-subtle h-100">
|
||||
<h6 class="fw-bold text-danger mb-2 d-flex align-items-center">
|
||||
<i class="bi bi-trash3-fill me-2"></i>Datos que se eliminarán:
|
||||
</h6>
|
||||
<ul class="small mb-0 ps-3 text-danger-emphasis">
|
||||
<li><strong>Historiales:</strong> Toda la bitácora histórica y registros previos de auditoría.</li>
|
||||
<li><strong>Reservas:</strong> Todas las reservas de aulas, asignaciones de espacios y estados.</li>
|
||||
<li><strong>Espacios y Sedes:</strong> Todas las aulas físicas, virtuales, recursos y edificios/sedes.</li>
|
||||
<li><strong>Académica:</strong> Carreras, materias, comisiones, docentes asignados, matrículas, notas y ciclos lectivos.</li>
|
||||
<li><strong>Colas de sincronización:</strong> Tareas pendientes o fallidas hacia sistemas externos.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="p-3 rounded-3 bg-success-subtle border border-success-subtle h-100">
|
||||
<h6 class="fw-bold text-success mb-2 d-flex align-items-center">
|
||||
<i class="bi bi-shield-check me-2"></i>Datos que se PRESERVAN intactos:
|
||||
</h6>
|
||||
<ul class="small mb-0 ps-3 text-success-emphasis">
|
||||
<li><strong>Cuentas de Usuarios:</strong> Todos los usuarios (Administradores, Bedeles, Docentes, Alumnos) con sus contraseñas activas.</li>
|
||||
<li><strong>Roles y Permisos (RBAC):</strong> Estructura completa de perfiles institucionales.</li>
|
||||
<li><strong>Configuración Global:</strong> Preferencias de correo SMTP, Single Sign-On, Moodle y opciones de interfaz.</li>
|
||||
<li><strong>Tipos de Hitos:</strong> Tipos maestros configurados (Parciales, Finales, TP, etc.).</li>
|
||||
<li><strong>Módulo de Administración:</strong> Todos los componentes de la pestaña Administración.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning py-2 px-3 small d-flex align-items-center mb-4">
|
||||
<i class="bi bi-shield-lock-fill text-warning fs-5 me-2 flex-shrink-0"></i>
|
||||
<div>
|
||||
Por estrictas razones de seguridad institucional, para ejecutar esta acción deberá ingresar la <strong>contraseña del usuario Administrador</strong> actualmente autenticado.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="button" class="btn btn-danger btn-sm px-4 fw-semibold shadow-sm" data-bs-toggle="modal" data-bs-target="#modalResetSystem">
|
||||
<i class="bi bi-radioactive me-2"></i>Reinicializar Sistema...
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info / Good Practices -->
|
||||
<div class="col-lg-4">
|
||||
<div class="card border-0 bg-body-tertiary p-3 rounded-3 mb-3">
|
||||
<h6 class="fw-bold mb-2"><i class="bi bi-info-circle text-primary me-1"></i>¿Cuándo usar esta función?</h6>
|
||||
<p class="small text-muted mb-2">
|
||||
Utilice la reinicialización cuando desee comenzar un nuevo ciclo lectivo desde cero, tras finalizar períodos de prueba o capacitación, o para cargar una nueva grilla de sedes y carreras sin arrastrar información residual.
|
||||
</p>
|
||||
<p class="small text-muted mb-0">
|
||||
Al conservar intactos los usuarios y las configuraciones de seguridad, el personal administrativo y docente mantiene su acceso ininterrumpido a la plataforma.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -580,6 +672,56 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Confirmar Reinicialización del Sistema -->
|
||||
<div class="modal fade" id="modalResetSystem" tabindex="-1" aria-labelledby="modalResetSystemLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-danger text-white py-2">
|
||||
<h6 class="modal-title fw-bold" id="modalResetSystemLabel">
|
||||
<i class="bi bi-shield-exclamation me-2"></i>Confirmación Crítica: Reinicio Total del Sistema
|
||||
</h6>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<div class="alert alert-danger py-2 px-3 small mb-3">
|
||||
<i class="bi bi-exclamation-triangle-fill me-1"></i>
|
||||
<strong>¡Atención!</strong> Esta acción es irreversible. Se eliminarán todas las reservas, aulas, sedes, materias, carreras, comisiones, notas y registros de auditoría previa.
|
||||
</div>
|
||||
|
||||
<p class="small text-muted mb-3">
|
||||
Las cuentas de usuario y la configuración del sistema permanecerán intactas. Para autorizar la purga definitiva, ingrese su <strong>contraseña de Administrador</strong>:
|
||||
</p>
|
||||
|
||||
<div id="resetFeedbackAlert"></div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="admin_reset_password" class="form-label small fw-bold">Contraseña del Administrador en sesión <span class="text-danger">*</span></label>
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text bg-body-tertiary"><i class="bi bi-key-fill text-danger"></i></span>
|
||||
<input type="password" class="form-control" id="admin_reset_password" placeholder="Ingrese su contraseña institucional" required autocomplete="current-password">
|
||||
<button class="btn btn-outline-secondary pass-toggle-btn" type="button" onclick="togglePassVisibility('admin_reset_password')" title="Mostrar/ocultar contraseña">
|
||||
<i class="bi bi-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="checkbox" id="confirm_reset_checkbox" onchange="document.getElementById('btnConfirmSystemReset').disabled = !this.checked">
|
||||
<label class="form-check-label small text-body" for="confirm_reset_checkbox">
|
||||
Entiendo las consecuencias irreversibles de esta purga y confirmo la reinicialización de los datos.
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer py-2 bg-light">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal" id="btnCancelReset">Cancelar</button>
|
||||
<button type="button" class="btn btn-sm btn-danger fw-semibold px-3" id="btnConfirmSystemReset" disabled onclick="executeSystemReset()">
|
||||
<i class="bi bi-radioactive me-1"></i>Confirmar Reinicio Completo
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function showAlert(message, type = 'success') {
|
||||
const container = document.getElementById('settingsAlertContainer');
|
||||
@@ -1109,6 +1251,63 @@ async function saveUiConfig(e) {
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Reinicialización Total del Sistema (Requiere Contraseña Admin)
|
||||
// -------------------------------------------------------------
|
||||
async function executeSystemReset() {
|
||||
const passwordInput = document.getElementById('admin_reset_password');
|
||||
const feedback = document.getElementById('resetFeedbackAlert');
|
||||
const btnConfirm = document.getElementById('btnConfirmSystemReset');
|
||||
const btnCancel = document.getElementById('btnCancelReset');
|
||||
const check = document.getElementById('confirm_reset_checkbox');
|
||||
|
||||
const password = (passwordInput ? passwordInput.value : '').trim();
|
||||
if (!password) {
|
||||
feedback.innerHTML = '<div class="alert alert-warning py-2 px-3 small mb-3"><i class="bi bi-exclamation-circle me-1"></i>Por favor ingrese su contraseña de administrador.</div>';
|
||||
if (passwordInput) passwordInput.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
btnConfirm.disabled = true;
|
||||
btnCancel.disabled = true;
|
||||
btnConfirm.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Reinicializando sistema...';
|
||||
feedback.innerHTML = '<div class="alert alert-info py-2 px-3 small mb-3"><span class="spinner-border spinner-border-sm me-1"></span>Procesando purga de datos operacionales...</div>';
|
||||
|
||||
try {
|
||||
const res = await fetch('/admin/settings/reset_system', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
if (res.ok && data.status === 'success') {
|
||||
feedback.innerHTML = `<div class="alert alert-success py-2 px-3 small mb-3"><i class="bi bi-check-circle-fill me-1"></i>${data.message}</div>`;
|
||||
showAlert(data.message, 'success');
|
||||
passwordInput.value = '';
|
||||
if (check) check.checked = false;
|
||||
|
||||
setTimeout(() => {
|
||||
const modalEl = document.getElementById('modalResetSystem');
|
||||
const modalInstance = bootstrap.Modal.getInstance(modalEl);
|
||||
if (modalInstance) modalInstance.hide();
|
||||
window.location.reload();
|
||||
}, 2000);
|
||||
} else {
|
||||
feedback.innerHTML = `<div class="alert alert-danger py-2 px-3 small mb-3"><i class="bi bi-x-circle-fill me-1"></i>${data.message || 'Error al autorizar la reinicialización.'}</div>`;
|
||||
btnConfirm.disabled = false;
|
||||
btnCancel.disabled = false;
|
||||
btnConfirm.innerHTML = '<i class="bi bi-radioactive me-1"></i>Confirmar Reinicio Completo';
|
||||
if (passwordInput) passwordInput.focus();
|
||||
}
|
||||
} catch (err) {
|
||||
feedback.innerHTML = `<div class="alert alert-danger py-2 px-3 small mb-3"><i class="bi bi-exclamation-triangle-fill me-1"></i>Error de comunicación: ${err.message}</div>`;
|
||||
btnConfirm.disabled = false;
|
||||
btnCancel.disabled = false;
|
||||
btnConfirm.innerHTML = '<i class="bi bi-radioactive me-1"></i>Confirmar Reinicio Completo';
|
||||
}
|
||||
}
|
||||
|
||||
// Cargar estadísticas y tareas al iniciar
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
refreshQueueStats();
|
||||
|
||||
Reference in New Issue
Block a user