feat: implementar ABM completo de comisiones, carreras y asignaturas con proteccion de integridad y corregir edificios y campus virtual
This commit is contained in:
@@ -26,6 +26,39 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notification Alerts -->
|
||||
{% if msg == 'created' %}
|
||||
<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 carrera ha sido registrada exitosamente.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'updated' %}
|
||||
<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>Los datos de la carrera se actualizaron correctamente.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif 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 carrera ha sido eliminada permanentemente del sistema.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error == 'has_subjects' %}
|
||||
<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>No es posible eliminar esta carrera porque tiene asignaturas vinculadas. Debe reasignar o eliminar primero sus materias.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error == 'conflict' %}
|
||||
<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>Ya existe una carrera registrada con ese nombre o código institucional.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error %}
|
||||
<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 solicitud en el catálogo de carreras.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Search & Filter Bar -->
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-body py-2">
|
||||
@@ -114,10 +147,15 @@
|
||||
<form method="POST" action="/admin/career_delete" class="d-inline"
|
||||
onsubmit="return confirm('¿Confirma que desea eliminar esta carrera permanentemente?');">
|
||||
<input type="hidden" name="id" value="{{ career.id }}">
|
||||
<button type="submit" class="btn btn-outline-danger py-0 px-2" title="Eliminar">
|
||||
<button type="submit" class="btn btn-outline-danger py-0 px-2" title="Eliminar Carrera">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-outline-secondary py-0 px-2 opacity-50"
|
||||
disabled title="No se puede eliminar: posee {{ c_stat.subjects_count }} asignatura(s) vinculada(s)">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
<!-- Commission Card -->
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-header border-0 bg-primary text-white rounded-top py-3">
|
||||
<div class="card-header border-0 bg-primary text-white rounded-top py-3 d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<i class="bi bi-diagram-3 fs-4"></i>
|
||||
<div>
|
||||
@@ -57,6 +57,11 @@
|
||||
<small class="opacity-75">{{ commission.semester }} {{ commission.year }}</small>
|
||||
</div>
|
||||
</div>
|
||||
{% if can_edit %}
|
||||
<button type="button" class="btn btn-sm btn-light py-1 px-2 fw-semibold text-primary" data-bs-toggle="modal" data-bs-target="#modalEditCommissionDetail">
|
||||
<i class="bi bi-pencil me-1"></i>Editar
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="fw-bold mb-1">{{ commission.subject.name }}</h5>
|
||||
@@ -389,4 +394,80 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Editar Datos de la Comisión -->
|
||||
{% if can_edit %}
|
||||
<div class="modal fade" id="modalEditCommissionDetail" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<form action="/admin/commission_edit" method="POST">
|
||||
<input type="hidden" name="id" value="{{ commission.id }}">
|
||||
<div class="modal-header bg-body-tertiary border-bottom py-3">
|
||||
<h5 class="modal-title fw-bold">
|
||||
<i class="bi bi-pencil-square text-primary me-2"></i>Editar Datos de la Comisión
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold small">Identificador / Código</label>
|
||||
<input type="text" class="form-control form-control-sm font-monospace" name="code" value="{{ commission.code }}" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-semibold small">Cuatrimestre</label>
|
||||
<select class="form-select form-select-sm" name="semester">
|
||||
<option value="1C" {% if commission.semester == '1C' %}selected{% endif %}>1C (Primer Cuatrimestre)</option>
|
||||
<option value="2C" {% if commission.semester == '2C' %}selected{% endif %}>2C (Segundo Cuatrimestre)</option>
|
||||
<option value="Anual" {% if commission.semester == 'Anual' %}selected{% endif %}>Anual</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-semibold small">Año</label>
|
||||
<input type="number" class="form-control form-control-sm" name="year" value="{{ commission.year }}" min="2020" max="2035">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold small">Turno</label>
|
||||
<select class="form-select form-select-sm" name="shift">
|
||||
<option value="Mañana" {% if commission.shift == 'Mañana' %}selected{% endif %}>Mañana (08:00 - 12:00)</option>
|
||||
<option value="Tarde" {% if commission.shift == 'Tarde' %}selected{% endif %}>Tarde (17:30 - 21:30)</option>
|
||||
<option value="Vespertino" {% if commission.shift == 'Vespertino' %}selected{% endif %}>Vespertino</option>
|
||||
<option value="Noche" {% if commission.shift == 'Noche' %}selected{% endif %}>Noche (19:00 - 23:00)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-semibold small">Cupo Máximo de Alumnos</label>
|
||||
<input type="number" class="form-control form-control-sm" name="max_students" value="{{ commission.max_students }}" min="1" max="300">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold small">Días y Horarios</label>
|
||||
<input type="text" class="form-control form-control-sm" name="schedule" value="{{ commission.schedule or '' }}" placeholder="Ej: Lun y Mié 17:30 a 21:30 hs">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold small">Enlace Aula Virtual (Meet, Teams, Zoom)</label>
|
||||
<input type="url" class="form-control form-control-sm" name="virtual_link" value="{{ commission.virtual_link or '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="active" id="detail_edit_active" value="on" {% if commission.active %}checked{% endif %}>
|
||||
<label class="form-check-label small fw-semibold" for="detail_edit_active">
|
||||
Comisión Activa
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-body-tertiary border-top py-2">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-primary btn-sm px-4">Guardar Cambios</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Flash Messages & Feedback -->
|
||||
{% if created %}
|
||||
{% if msg == 'created' or created %}
|
||||
<div class="alert alert-success alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-check-circle-fill fs-5 text-success"></i>
|
||||
<div>
|
||||
@@ -30,6 +30,62 @@
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'updated' %}
|
||||
<div class="alert alert-success alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-check-circle-fill fs-5 text-success"></i>
|
||||
<div>
|
||||
<strong>¡Comisión actualizada!</strong> Los datos de la comisión, cupos y horarios fueron guardados correctamente.
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'toggled' %}
|
||||
<div class="alert alert-info alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-info-circle-fill fs-5 text-info"></i>
|
||||
<div>
|
||||
El estado de actividad de la comisión ha sido modificado.
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'deleted' %}
|
||||
<div class="alert alert-success alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-check-circle-fill fs-5 text-success"></i>
|
||||
<div>
|
||||
La comisión ha sido eliminada permanentemente del sistema.
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'deactivated' %}
|
||||
<div class="alert alert-warning alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-exclamation-triangle-fill fs-5 text-warning"></i>
|
||||
<div>
|
||||
La comisión posee reservas horarias o alumnos inscriptos. Por integridad del historial académico fue <strong>desactivada</strong>.
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error == 'create' %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-x-circle-fill fs-5 text-danger"></i>
|
||||
<div>No se pudo crear la comisión. Verifique que no exista otra comisión con el mismo código en el mismo período.</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error == 'edit' %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-x-circle-fill fs-5 text-danger"></i>
|
||||
<div>Ocurrió un error al actualizar los datos de la comisión.</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error == 'delete' %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-x-circle-fill fs-5 text-danger"></i>
|
||||
<div>Ocurrió un error al intentar eliminar la comisión.</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif error %}
|
||||
<div class="alert alert-danger alert-dismissible fade show d-flex align-items-center gap-2 mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-x-circle-fill fs-5 text-danger"></i>
|
||||
<div>Ocurrió una eventualidad procesando la comisión.</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -170,10 +226,44 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-end pe-3">
|
||||
<a href="/admin/commission_detail?id={{ comm.id }}"
|
||||
class="btn btn-sm btn-outline-primary" title="Ver y gestionar comisión">
|
||||
<i class="bi bi-gear me-1"></i>Gestionar
|
||||
</a>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="/admin/commission_detail?id={{ comm.id }}"
|
||||
class="btn btn-outline-primary py-0 px-2" title="Gestionar e Inscribir Alumnos">
|
||||
<i class="bi bi-gear"></i>
|
||||
</a>
|
||||
<button type="button" class="btn btn-outline-secondary py-0 px-2"
|
||||
data-bs-toggle="modal" data-bs-target="#modalEditCommission"
|
||||
data-id="{{ comm.id }}"
|
||||
data-code="{{ comm.code }}"
|
||||
data-subject-id="{{ comm.subject_id }}"
|
||||
data-academic-term-id="{{ comm.academic_term_id or '' }}"
|
||||
data-semester="{{ comm.semester }}"
|
||||
data-year="{{ comm.year }}"
|
||||
data-shift="{{ comm.shift }}"
|
||||
data-teacher-id="{{ comm.teacher_id or '' }}"
|
||||
data-max-students="{{ comm.max_students }}"
|
||||
data-schedule="{{ comm.schedule or '' }}"
|
||||
data-virtual-link="{{ comm.virtual_link or '' }}"
|
||||
data-active="{{ 'true' if comm.active else 'false' }}"
|
||||
title="Editar Comisión">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<form method="POST" action="/admin/commission_toggle" class="d-inline">
|
||||
<input type="hidden" name="id" value="{{ comm.id }}">
|
||||
<button type="submit" class="btn btn-outline-warning py-0 px-2"
|
||||
title="{% if comm.active %}Desactivar comisión{% else %}Activar comisión{% endif %}">
|
||||
<i class="bi {% if comm.active %}bi-pause{% else %}bi-play{% endif %}"></i>
|
||||
</button>
|
||||
</form>
|
||||
<button type="button" class="btn btn-outline-danger py-0 px-2"
|
||||
data-bs-toggle="modal" data-bs-target="#modalDeleteCommission"
|
||||
data-id="{{ comm.id }}"
|
||||
data-code="{{ comm.get_full_code() }}"
|
||||
data-subject-name="{{ comm.subject.name }}"
|
||||
title="Eliminar Comisión">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -366,13 +456,171 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Editar Comisión -->
|
||||
<div class="modal fade" id="modalEditCommission" tabindex="-1" aria-labelledby="modalEditCommissionLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-body-tertiary border-bottom py-3">
|
||||
<h5 class="modal-title fw-bold" id="modalEditCommissionLabel">
|
||||
<i class="bi bi-pencil-square text-primary me-2"></i>Editar Comisión de Cursada
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="/admin/commission_edit" method="POST" id="formEditCommission">
|
||||
<input type="hidden" name="id" id="edit_commission_id">
|
||||
<div class="modal-body p-4">
|
||||
<!-- 1. Asignatura y Código -->
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-7">
|
||||
<label for="edit_subject_id" class="form-label fw-semibold small">
|
||||
<i class="bi bi-book text-primary me-1"></i>Asignatura Asociada <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select class="form-select form-select-sm" id="edit_subject_id" name="subject_id" required>
|
||||
{% for subj in subjects %}
|
||||
<option value="{{ subj.id }}">{{ subj.code }} — {{ subj.name }} ({{ subj.career_name or 'General' }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label for="edit_code" class="form-label fw-semibold small">
|
||||
<i class="bi bi-tag text-primary me-1"></i>Identificador / Código <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm font-monospace" id="edit_code" name="code" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. Ciclo Lectivo, Semestre y Año -->
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-5">
|
||||
<label for="edit_academic_term_id" class="form-label fw-semibold small">
|
||||
<i class="bi bi-calendar-event text-info me-1"></i>Ciclo Lectivo
|
||||
</label>
|
||||
<select class="form-select form-select-sm" id="edit_academic_term_id" name="academic_term_id">
|
||||
<option value="">-- Sin ciclo específico --</option>
|
||||
{% for term in academic_terms %}
|
||||
<option value="{{ term.id }}" data-year="{{ term.year }}" data-period="{{ term.period_type or '' }}" data-code="{{ term.code }}">
|
||||
{{ term.name }} ({{ term.code }}) - {{ term.year }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="edit_semester" class="form-label fw-semibold small">Período / Cuatrimestre</label>
|
||||
<select class="form-select form-select-sm" id="edit_semester" name="semester">
|
||||
<option value="1C">1C (Primer Cuatrimestre)</option>
|
||||
<option value="2C">2C (Segundo Cuatrimestre)</option>
|
||||
<option value="Anual">Anual</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="edit_year" class="form-label fw-semibold small">Año Académico</label>
|
||||
<input type="number" class="form-control form-control-sm" id="edit_year" name="year" min="2020" max="2035">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="edit_shift" class="form-label fw-semibold small">Turno de Cursada</label>
|
||||
<select class="form-select form-select-sm" id="edit_shift" name="shift">
|
||||
<option value="Mañana">Mañana (08:00 - 12:00)</option>
|
||||
<option value="Tarde">Tarde (17:30 - 21:30)</option>
|
||||
<option value="Vespertino">Vespertino</option>
|
||||
<option value="Noche">Noche (19:00 - 23:00)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="edit_max_students" class="form-label fw-semibold small">Cupo Máximo de Alumnos</label>
|
||||
<input type="number" class="form-control form-control-sm" id="edit_max_students" name="max_students" min="1" max="300">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Docente Responsable -->
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-12">
|
||||
<label for="edit_teacher_id" class="form-label fw-semibold small">
|
||||
<i class="bi bi-person-video3 text-info me-1"></i>Docente Responsable (Titular)
|
||||
</label>
|
||||
<select class="form-select form-select-sm" id="edit_teacher_id" name="teacher_id">
|
||||
<option value="">-- Sin asignar (se puede asignar más tarde) --</option>
|
||||
{% for t in teachers %}
|
||||
<option value="{{ t.id }}">{{ t.name }} ({{ t.email }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Días y Horarios -->
|
||||
<div class="mb-3">
|
||||
<label for="edit_schedule" class="form-label fw-semibold small">
|
||||
<i class="bi bi-calendar-week text-warning me-1"></i>Días y Horarios de Cursada
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm" id="edit_schedule" name="schedule" placeholder="Ej: Lun y Mié 17:30 a 21:30 hs">
|
||||
</div>
|
||||
|
||||
<!-- 5. Enlace Virtual -->
|
||||
<div class="mb-3">
|
||||
<label for="edit_virtual_link" class="form-label fw-semibold small">
|
||||
<i class="bi bi-camera-video text-primary me-1"></i>Enlace a Aula Virtual (Meet, Zoom, Teams)
|
||||
</label>
|
||||
<input type="url" class="form-control form-control-sm" id="edit_virtual_link" name="virtual_link">
|
||||
</div>
|
||||
|
||||
<!-- 6. Estado Activo -->
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="active" id="edit_active" value="on">
|
||||
<label class="form-check-label small fw-semibold" for="edit_active">
|
||||
Comisión Activa para Cursada y Reservas
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-body-tertiary border-top py-2">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-primary btn-sm px-4 shadow-sm">
|
||||
<i class="bi bi-save me-1"></i>Guardar Cambios
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Eliminar Comisión -->
|
||||
<div class="modal fade" id="modalDeleteCommission" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<form action="/admin/commission_delete" method="POST">
|
||||
<input type="hidden" name="id" id="delete_commission_id">
|
||||
<div class="modal-header bg-danger text-white py-3">
|
||||
<h5 class="modal-title h6 fw-bold">
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>Eliminar Comisión
|
||||
</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 comisión <strong id="delete_commission_code" class="font-monospace"></strong> vinculada a <strong id="delete_commission_subject"></strong>?</p>
|
||||
<div class="alert alert-warning small mb-0">
|
||||
<i class="bi bi-info-circle me-1"></i>
|
||||
<strong>Integridad Académica:</strong> Si la comisión posee reservas en aulas o alumnos inscriptos, el sistema la <strong>desactivará automáticamente</strong> para salvaguardar las actas y calificaciones.
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-body-tertiary border-top py-2">
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-danger btn-sm px-3">
|
||||
<i class="bi bi-trash me-1"></i>Confirmar Eliminación
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const termSelect = document.getElementById('add_academic_term_id');
|
||||
const yearInput = document.getElementById('add_year');
|
||||
const semSelect = document.getElementById('add_semester');
|
||||
// Sincronización Ciclo Lectivo en Alta
|
||||
const addTermSelect = document.getElementById('add_academic_term_id');
|
||||
const addYearInput = document.getElementById('add_year');
|
||||
const addSemSelect = document.getElementById('add_semester');
|
||||
|
||||
function syncTerm() {
|
||||
function syncTerm(termSelect, yearInput, semSelect) {
|
||||
if (!termSelect) return;
|
||||
const opt = termSelect.options[termSelect.selectedIndex];
|
||||
if (!opt || !opt.value) return;
|
||||
@@ -391,9 +639,51 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (termSelect) {
|
||||
termSelect.addEventListener('change', syncTerm);
|
||||
if (termSelect.value) syncTerm();
|
||||
if (addTermSelect) {
|
||||
addTermSelect.addEventListener('change', () => syncTerm(addTermSelect, addYearInput, addSemSelect));
|
||||
if (addTermSelect.value) syncTerm(addTermSelect, addYearInput, addSemSelect);
|
||||
}
|
||||
|
||||
// Sincronización Ciclo Lectivo en Edición
|
||||
const editTermSelect = document.getElementById('edit_academic_term_id');
|
||||
const editYearInput = document.getElementById('edit_year');
|
||||
const editSemSelect = document.getElementById('edit_semester');
|
||||
|
||||
if (editTermSelect) {
|
||||
editTermSelect.addEventListener('change', () => syncTerm(editTermSelect, editYearInput, editSemSelect));
|
||||
}
|
||||
|
||||
// Poblar Modal Editar Comisión
|
||||
const modalEdit = document.getElementById('modalEditCommission');
|
||||
if (modalEdit) {
|
||||
modalEdit.addEventListener('show.bs.modal', function(event) {
|
||||
const btn = event.relatedTarget;
|
||||
if (!btn) return;
|
||||
document.getElementById('edit_commission_id').value = btn.getAttribute('data-id') || '';
|
||||
document.getElementById('edit_code').value = btn.getAttribute('data-code') || '';
|
||||
document.getElementById('edit_subject_id').value = btn.getAttribute('data-subject-id') || '';
|
||||
document.getElementById('edit_academic_term_id').value = btn.getAttribute('data-academic-term-id') || '';
|
||||
document.getElementById('edit_semester').value = btn.getAttribute('data-semester') || '1C';
|
||||
document.getElementById('edit_year').value = btn.getAttribute('data-year') || '2026';
|
||||
document.getElementById('edit_shift').value = btn.getAttribute('data-shift') || 'Mañana';
|
||||
document.getElementById('edit_teacher_id').value = btn.getAttribute('data-teacher-id') || '';
|
||||
document.getElementById('edit_max_students').value = btn.getAttribute('data-max-students') || '40';
|
||||
document.getElementById('edit_schedule').value = btn.getAttribute('data-schedule') || '';
|
||||
document.getElementById('edit_virtual_link').value = btn.getAttribute('data-virtual-link') || '';
|
||||
document.getElementById('edit_active').checked = (btn.getAttribute('data-active') === 'true');
|
||||
});
|
||||
}
|
||||
|
||||
// Poblar Modal Eliminar Comisión
|
||||
const modalDel = document.getElementById('modalDeleteCommission');
|
||||
if (modalDel) {
|
||||
modalDel.addEventListener('show.bs.modal', function(event) {
|
||||
const btn = event.relatedTarget;
|
||||
if (!btn) return;
|
||||
document.getElementById('delete_commission_id').value = btn.getAttribute('data-id') || '';
|
||||
document.getElementById('delete_commission_code').textContent = btn.getAttribute('data-code') || '';
|
||||
document.getElementById('delete_commission_subject').textContent = btn.getAttribute('data-subject-name') || '';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -27,7 +27,22 @@
|
||||
</div>
|
||||
|
||||
<!-- Notification Alerts -->
|
||||
{% if msg == 'deleted' %}
|
||||
{% if msg == 'created' %}
|
||||
<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 registrada exitosamente en el catálogo académico.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'updated' %}
|
||||
<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>Los datos de la asignatura fueron actualizados correctamente.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif msg == 'toggled' %}
|
||||
<div class="alert alert-info alert-dismissible fade show mb-4 shadow-sm" role="alert">
|
||||
<i class="bi bi-info-circle-fill me-2"></i>El estado de actividad de la asignatura ha sido modificado.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% elif 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>
|
||||
@@ -37,11 +52,21 @@
|
||||
<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 == 'conflict' %}
|
||||
<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>Ya existe una asignatura con ese código o denominación.
|
||||
<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>
|
||||
{% elif error %}
|
||||
<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 operación sobre la asignatura.
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Filters Bar -->
|
||||
|
||||
Reference in New Issue
Block a user