feat: implementacion de dashboards por rol, soporte de clases virtuales concurrentes en importador de sheets y cartelera del dia
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Bitácora de Auditoría - Edu-Space Admin{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid pt-5 mt-4">
|
||||
<!-- Header -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 class="h3 mb-1">
|
||||
<i class="bi bi-shield-check text-primary me-2"></i>Registro de Auditoría Institucional
|
||||
</h1>
|
||||
<p class="text-muted small mb-0">Trazabilidad completa de operaciones, modificaciones y eventos de seguridad</p>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/main/dashboard" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-arrow-left me-1"></i>Volver al Panel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filtros -->
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-body p-3">
|
||||
<form method="GET" action="/admin/audit_logs" class="row g-2 align-items-center">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text bg-transparent"><i class="bi bi-search"></i></span>
|
||||
<input type="text" name="search" class="form-control" placeholder="Buscar por email, IP o detalles..." value="{{ search }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="module" class="form-select form-select-sm">
|
||||
<option value="">Todos los módulos</option>
|
||||
{% for mod in modules %}
|
||||
<option value="{{ mod }}" {% if current_module == mod %}selected{% endif %}>{{ mod|capitalize }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="action" class="form-select form-select-sm">
|
||||
<option value="">Todas las acciones</option>
|
||||
{% for act in actions %}
|
||||
<option value="{{ act }}" {% if current_action == act %}selected{% endif %}>{{ act }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-flex gap-1">
|
||||
<button type="submit" class="btn btn-primary btn-sm flex-grow-1">
|
||||
<i class="bi bi-filter me-1"></i>Filtrar
|
||||
</button>
|
||||
{% if search or current_module or current_action %}
|
||||
<a href="/admin/audit_logs" class="btn btn-outline-secondary btn-sm" title="Limpiar filtros">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabla de Auditoría -->
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body p-0">
|
||||
{% if audit_logs %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light small text-uppercase">
|
||||
<tr>
|
||||
<th class="ps-3">Fecha / Hora</th>
|
||||
<th>Usuario</th>
|
||||
<th>Acción</th>
|
||||
<th>Módulo</th>
|
||||
<th>ID Entidad</th>
|
||||
<th>Detalles</th>
|
||||
<th class="pe-3">IP</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for log in audit_logs %}
|
||||
<tr>
|
||||
<td class="ps-3 text-nowrap">
|
||||
<span class="small font-monospace">{{ log.created_at }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="fw-semibold small">{{ log.user_email or 'Sistema' }}</div>
|
||||
</td>
|
||||
<td>
|
||||
{% if log.action == 'CREATE' %}
|
||||
<span class="badge bg-success-subtle text-success border border-success-subtle">{{ log.action }}</span>
|
||||
{% elif log.action == 'UPDATE' %}
|
||||
<span class="badge bg-primary-subtle text-primary border border-primary-subtle">{{ log.action }}</span>
|
||||
{% elif log.action == 'DELETE' %}
|
||||
<span class="badge bg-danger-subtle text-danger border border-danger-subtle">{{ log.action }}</span>
|
||||
{% elif 'LOGIN' in log.action %}
|
||||
<span class="badge bg-info-subtle text-info border border-info-subtle">{{ log.action }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary-subtle text-secondary border">{{ log.action }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-body-secondary text-body border font-monospace small">{{ log.module }}</span>
|
||||
</td>
|
||||
<td class="font-monospace small text-muted">
|
||||
{{ log.entity_id or '-' }}
|
||||
</td>
|
||||
<td class="small text-muted" style="max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="{{ log.details }}">
|
||||
{{ log.details or '-' }}
|
||||
</td>
|
||||
<td class="pe-3 font-monospace small text-muted">
|
||||
{{ log.ip_address or '-' }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Paginación -->
|
||||
{% if pagination.pages > 1 %}
|
||||
<div class="p-3 border-top d-flex justify-content-between align-items-center">
|
||||
<small class="text-muted">
|
||||
Mostrando página {{ pagination.page }} de {{ pagination.pages }} ({{ pagination.total }} registros)
|
||||
</small>
|
||||
<nav>
|
||||
<ul class="pagination pagination-sm mb-0">
|
||||
<li class="page-item {% if not pagination.has_prev %}disabled{% endif %}">
|
||||
<a class="page-link" href="/admin/audit_logs">
|
||||
«
|
||||
</a>
|
||||
</li>
|
||||
{% for p in pagination.iter_pages(left_edge=2, left_current=2, right_current=3, right_edge=2) %}
|
||||
{% if p %}
|
||||
<li class="page-item {% if p == pagination.page %}active{% endif %}">
|
||||
<a class="page-link" href="/admin/audit_logs">{{ p }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="page-item disabled"><span class="page-link">…</span></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<li class="page-item {% if not pagination.has_next %}disabled{% endif %}">
|
||||
<a class="page-link" href="/admin/audit_logs">
|
||||
»
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<div class="text-center py-5">
|
||||
<i class="bi bi-shield-slash text-muted fs-1 d-block mb-2"></i>
|
||||
<h6 class="fw-bold">No se encontraron registros de auditoría</h6>
|
||||
<p class="text-muted small">Los eventos del sistema se registrarán automáticamente a medida que ocurran cambios.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user