feat: completar Fase 2 del Roadmap MVP (Co-docencia, Matriz de Conflictos y Regla Diaria) y auditoria de seguridad
This commit is contained in:
@@ -20,12 +20,30 @@
|
||||
<i class="bi bi-plus-lg me-1"></i>Nueva Asignatura
|
||||
</button>
|
||||
{% endif %}
|
||||
<a href="/schedule/commissions_view" class="btn btn-outline-secondary">
|
||||
<a href="/admin/commissions_list" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-diagram-3 me-1"></i>Ver Comisiones
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notification Alerts -->
|
||||
{% if msg == 'deleted' %}
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-check-circle-fill me-2"></i>La asignatura ha sido eliminada permanentemente del sistema.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'deactivated' %}
|
||||
<div class="alert alert-warning alert-dismissible fade show mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>La asignatura posee comisiones históricas asociadas. Por integridad de los registros académicos fue <strong>desactivada</strong>.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error == 'delete' %}
|
||||
<div class="alert alert-danger alert-dismissible fade show mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-x-circle-fill me-2"></i>Ocurrió un error al procesar la eliminación de la asignatura.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Filters Bar -->
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-body py-2">
|
||||
@@ -133,7 +151,15 @@
|
||||
<td class="text-end">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" class="btn btn-outline-secondary py-0 px-2"
|
||||
data-bs-toggle="modal" data-bs-target="#modalEditSubject{{ s.id }}"
|
||||
data-bs-toggle="modal" data-bs-target="#modalEditSubject"
|
||||
data-id="{{ s.id }}"
|
||||
data-code="{{ s.code }}"
|
||||
data-name="{{ s.name }}"
|
||||
data-credits="{{ s.credits }}"
|
||||
data-career-id="{{ s.career_id or '' }}"
|
||||
data-department="{{ s.department or '' }}"
|
||||
data-description="{{ s.description or '' }}"
|
||||
data-active="{{ 'true' if s.is_active else 'false' }}"
|
||||
title="Editar Asignatura">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
@@ -144,64 +170,14 @@
|
||||
<i class="bi {% if s.is_active %}bi-pause{% else %}bi-play{% endif %}"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Modal Editar Asignatura -->
|
||||
<div class="modal fade text-start" id="modalEditSubject{{ s.id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="POST" action="/admin/subject_edit">
|
||||
<input type="hidden" name="id" value="{{ s.id }}">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title h6 fw-bold">
|
||||
<i class="bi bi-pencil-square text-primary me-2"></i>Editar Asignatura
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label small fw-semibold">Código *</label>
|
||||
<input type="text" name="code" class="form-control form-control-sm font-monospace" value="{{ s.code }}" required>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<label class="form-label small fw-semibold">Créditos</label>
|
||||
<input type="number" name="credits" class="form-control form-control-sm" value="{{ s.credits }}" min="1" max="20">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Nombre de la Asignatura *</label>
|
||||
<input type="text" name="name" class="form-control form-control-sm" value="{{ s.name }}" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Carrera Vinculada</label>
|
||||
<select name="career_id" class="form-select form-select-sm">
|
||||
<option value="">Sin carrera específica (General)</option>
|
||||
{% for c in careers %}
|
||||
<option value="{{ c.id }}" {% if s.career_id == c.id %}selected{% endif %}>{{ c.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Departamento / Área</label>
|
||||
<input type="text" name="department" class="form-control form-control-sm" value="{{ s.department or '' }}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Descripción / Objetivos</label>
|
||||
<textarea name="description" class="form-control form-control-sm" rows="2">{{ s.description or '' }}</textarea>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="activeSubj{{ s.id }}" {% if s.is_active %}checked{% endif %}>
|
||||
<label class="form-check-label small" for="activeSubj{{ s.id }}">Asignatura Activa</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary">Guardar Cambios</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-danger py-0 px-2"
|
||||
data-bs-toggle="modal" data-bs-target="#modalDeleteSubject"
|
||||
data-id="{{ s.id }}"
|
||||
data-code="{{ s.code }}"
|
||||
data-name="{{ s.name }}"
|
||||
title="Eliminar Asignatura">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
@@ -304,5 +280,124 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Editar Asignatura (Global fuera de la tabla para evitar problemas de visualización) -->
|
||||
<div class="modal fade" id="modalEditSubject" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="POST" action="/admin/subject_edit" id="formEditSubject">
|
||||
<input type="hidden" name="id" id="editSubjectId">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title h6 fw-bold">
|
||||
<i class="bi bi-pencil-square text-primary me-2"></i>Editar Asignatura
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label small fw-semibold">Código *</label>
|
||||
<input type="text" name="code" id="editSubjectCode" class="form-control form-control-sm font-monospace" required>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<label class="form-label small fw-semibold">Créditos</label>
|
||||
<input type="number" name="credits" id="editSubjectCredits" class="form-control form-control-sm" min="1" max="20">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Nombre de la Asignatura *</label>
|
||||
<input type="text" name="name" id="editSubjectName" class="form-control form-control-sm" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Carrera Vinculada</label>
|
||||
<select name="career_id" id="editSubjectCareer" class="form-select form-select-sm">
|
||||
<option value="">Sin carrera específica (General)</option>
|
||||
{% for c in careers %}
|
||||
<option value="{{ c.id }}">{{ c.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Departamento / Área</label>
|
||||
<input type="text" name="department" id="editSubjectDept" class="form-control form-control-sm">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-semibold">Descripción / Objetivos</label>
|
||||
<textarea name="description" id="editSubjectDesc" class="form-control form-control-sm" rows="2"></textarea>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="is_active" id="editSubjectActive">
|
||||
<label class="form-check-label small" for="editSubjectActive">Asignatura Activa</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary">Guardar Cambios</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Eliminar Asignatura -->
|
||||
<div class="modal fade" id="modalDeleteSubject" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<form method="POST" action="/admin/subject_delete">
|
||||
<input type="hidden" name="id" id="deleteSubjectId">
|
||||
<div class="modal-header bg-danger text-white">
|
||||
<h5 class="modal-title h6 fw-bold">
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>Eliminar Asignatura
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body py-4">
|
||||
<p class="mb-2">¿Estás seguro de que deseas eliminar la asignatura <strong id="deleteSubjectName"></strong> (<span class="font-monospace" id="deleteSubjectCode"></span>)?</p>
|
||||
<div class="alert alert-warning small mb-0">
|
||||
<i class="bi bi-info-circle me-1"></i>
|
||||
<strong>Aviso de integridad:</strong> Si la materia no posee comisiones vinculadas se eliminará permanentemente. Si ya posee comisiones históricas o cursadas, el sistema la <strong>desactivará automáticamente</strong> para resguardar las actas académicas.
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-sm btn-danger">Confirmar Eliminación</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Populate Edit Subject Modal
|
||||
var modalEdit = document.getElementById('modalEditSubject');
|
||||
if (modalEdit) {
|
||||
modalEdit.addEventListener('show.bs.modal', function(event) {
|
||||
var btn = event.relatedTarget;
|
||||
if (!btn) return;
|
||||
document.getElementById('editSubjectId').value = btn.getAttribute('data-id') || '';
|
||||
document.getElementById('editSubjectCode').value = btn.getAttribute('data-code') || '';
|
||||
document.getElementById('editSubjectName').value = btn.getAttribute('data-name') || '';
|
||||
document.getElementById('editSubjectCredits').value = btn.getAttribute('data-credits') || '4';
|
||||
document.getElementById('editSubjectCareer').value = btn.getAttribute('data-career-id') || '';
|
||||
document.getElementById('editSubjectDept').value = btn.getAttribute('data-department') || '';
|
||||
document.getElementById('editSubjectDesc').value = btn.getAttribute('data-description') || '';
|
||||
document.getElementById('editSubjectActive').checked = (btn.getAttribute('data-active') === 'true');
|
||||
});
|
||||
}
|
||||
|
||||
// Populate Delete Subject Modal
|
||||
var modalDel = document.getElementById('modalDeleteSubject');
|
||||
if (modalDel) {
|
||||
modalDel.addEventListener('show.bs.modal', function(event) {
|
||||
var btn = event.relatedTarget;
|
||||
if (!btn) return;
|
||||
document.getElementById('deleteSubjectId').value = btn.getAttribute('data-id') || '';
|
||||
document.getElementById('deleteSubjectCode').textContent = btn.getAttribute('data-code') || '';
|
||||
document.getElementById('deleteSubjectName').textContent = btn.getAttribute('data-name') || '';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user