feat(ui/rbac): ordenar navegacion segun estandares de la industria y personalizar dashboards por rol (Admin, Bedelia, Docente, Alumno)
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{% trans %}Bitácora de Auditoría - Edu-Space Admin{% endtrans %}{% 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>{% trans %}Registro de Auditoría Institucional{% endtrans %}
|
||||
</h1>
|
||||
<p class="text-muted small mb-0">{% trans %}Trazabilidad completa de operaciones, modificaciones y eventos de seguridad{% endtrans %}</p>
|
||||
</div>
|
||||
<div>
|
||||
<a href="{{ url_for('main.dashboard') }}" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-arrow-left me-1"></i>{% trans %}Volver al Panel{% endtrans %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filtros -->
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-body p-3">
|
||||
<form method="GET" action="{{ url_for('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="{% trans %}Buscar por email, IP o detalles...{% endtrans %}" value="{{ search }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select name="module" class="form-select form-select-sm">
|
||||
<option value="">{% trans %}Todos los módulos{% endtrans %}</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="">{% trans %}Todas las acciones{% endtrans %}</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>{% trans %}Filtrar{% endtrans %}
|
||||
</button>
|
||||
{% if search or current_module or current_action %}
|
||||
<a href="{{ url_for('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">{% trans %}Fecha / Hora{% endtrans %}</th>
|
||||
<th>{% trans %}Usuario{% endtrans %}</th>
|
||||
<th>{% trans %}Acción{% endtrans %}</th>
|
||||
<th>{% trans %}Módulo{% endtrans %}</th>
|
||||
<th>{% trans %}ID Entidad{% endtrans %}</th>
|
||||
<th>{% trans %}Detalles{% endtrans %}</th>
|
||||
<th class="pe-3">{% trans %}IP{% endtrans %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for log in audit_logs %}
|
||||
<tr>
|
||||
<td class="ps-3 text-nowrap">
|
||||
<span class="small font-monospace">{{ log.created_at.strftime('%Y-%m-%d %H:%M:%S') }}</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">
|
||||
{% trans %}Mostrando página{% endtrans %} {{ pagination.page }} {% trans %}de{% endtrans %} {{ pagination.pages }} ({{ pagination.total }} {% trans %}registros{% endtrans %})
|
||||
</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="{{ url_for('admin.audit_logs', page=pagination.prev_num, search=search, module=current_module, action=current_action) }}">
|
||||
«
|
||||
</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="{{ url_for('admin.audit_logs', page=p, search=search, module=current_module, action=current_action) }}">{{ 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="{{ url_for('admin.audit_logs', page=pagination.next_num, search=search, module=current_module, action=current_action) }}">
|
||||
»
|
||||
</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">{% trans %}No se encontraron registros de auditoría{% endtrans %}</h6>
|
||||
<p class="text-muted small">{% trans %}Los eventos del sistema se registrarán automáticamente a medida que ocurran cambios.{% endtrans %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
+174
-87
@@ -46,92 +46,171 @@
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
{% set user_role = current_user.get_institutional_role() %}
|
||||
<ul class="navbar-nav me-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('main.dashboard') }}">
|
||||
<i class="bi bi-speedometer2"></i> {% trans %}Dashboard{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-door-open"></i> {% trans %}Classrooms{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms') }}">
|
||||
<i class="bi bi-list"></i> {% trans %}All Classrooms{% endtrans %}
|
||||
</a></li>
|
||||
{% if current_user.has_permission('classrooms', 'read_write') %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.add_classroom') }}">
|
||||
<i class="bi bi-plus-circle"></i> {% trans %}Add Classroom{% endtrans %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('buildings.list_buildings') }}">
|
||||
<i class="bi bi-buildings"></i> {% trans %}Buildings{% endtrans %}
|
||||
</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-calendar3"></i> {% trans %}Schedule{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.calendar_view') }}">
|
||||
<i class="bi bi-calendar-week"></i> {% trans %}Calendar View{% endtrans %}
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.list_reservations') }}">
|
||||
<i class="bi bi-list-check"></i> {% trans %}All Reservations{% endtrans %}
|
||||
</a></li>
|
||||
{% if current_user.has_permission('reservations', 'read_write') %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.add_reservation') }}">
|
||||
<i class="bi bi-plus-circle"></i> {% trans %}New Reservation{% endtrans %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.today_schedule') }}">
|
||||
<i class="bi bi-calendar-today"></i> {% trans %}Today's Schedule{% endtrans %}
|
||||
</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.commissions_view') }}">
|
||||
<i class="bi bi-diagram-3 me-2 text-primary"></i>{% trans %}Comisiones y Cursadas{% endtrans %}
|
||||
</a></li>
|
||||
{% if current_user.has_permission('optimizer', 'read') or (current_user.role and current_user.role|upper == 'ADMIN') %}
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('genetic_algorithm_web.genetic_optimizer') }}">
|
||||
<i class="bi bi-cpu text-info me-2"></i>{% trans %}Optimizador de Aulas (IA){% endtrans %}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
{% if current_user.is_authenticated and current_user.can_manage() %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-shield-lock"></i> {% trans %}Gestión{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm" style="min-width: 260px;">
|
||||
<!-- Espacios & Infraestructura -->
|
||||
<li class="dropdown-header text-uppercase small fw-bold text-muted py-1" style="font-size: 0.68rem; letter-spacing: 0.5px;">{% trans %}Espacios e Infraestructura{% endtrans %}</li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('buildings.list_buildings') }}"><i class="bi bi-buildings me-2 text-secondary"></i>{% trans %}Edificios y Sedes{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='physical') }}"><i class="bi bi-door-open me-2 text-primary"></i>{% trans %}Aulas Presenciales{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='virtual') }}"><i class="bi bi-camera-video me-2 text-info"></i>{% trans %}Aulas Virtuales (Reunión){% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.occupancy_metrics') }}"><i class="bi bi-graph-up-arrow me-2 text-success"></i>{% trans %}Gestión de Ocupación, Métricas{% endtrans %}</a></li>
|
||||
|
||||
<li><hr class="dropdown-divider my-1"></li>
|
||||
<!-- Gestión Académica -->
|
||||
<li class="dropdown-header text-uppercase small fw-bold text-muted py-1" style="font-size: 0.68rem; letter-spacing: 0.5px;">{% trans %}Gestión Académica{% endtrans %}</li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.careers_list') }}"><i class="bi bi-mortarboard me-2 text-primary"></i>{% trans %}Carreras{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.subjects_list') }}"><i class="bi bi-book me-2 text-info"></i>{% trans %}Asignaturas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.commissions_view') }}"><i class="bi bi-diagram-3 me-2 text-primary"></i>{% trans %}Comisiones y Cursadas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.academic_terms_list') }}"><i class="bi bi-calendar-range me-2 text-warning"></i>{% trans %}Ciclo Lectivo{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.list_reservations') }}"><i class="bi bi-calendar-check me-2 text-warning"></i>{% trans %}Gestión de Reservas{% endtrans %}</a></li>
|
||||
{% if user_role == 'admin' %}
|
||||
<!-- ================= ADMIN NAVIGATION ================= -->
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('main.dashboard') }}">
|
||||
<i class="bi bi-speedometer2 me-1"></i>{% trans %}Panel General{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-door-open me-1"></i>{% trans %}Espacios & Sedes{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='physical') }}"><i class="bi bi-door-open me-2 text-primary"></i>{% trans %}Aulas Presenciales{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='virtual') }}"><i class="bi bi-camera-video me-2 text-info"></i>{% trans %}Aulas Virtuales (Reunión){% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms') }}"><i class="bi bi-grid me-2 text-secondary"></i>{% trans %}Todas las Aulas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.add_classroom') }}"><i class="bi bi-plus-circle me-2 text-success"></i>{% trans %}Nueva Aula{% endtrans %}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('buildings.list_buildings') }}"><i class="bi bi-buildings me-2 text-secondary"></i>{% trans %}Edificios y Sedes{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.occupancy_metrics') }}"><i class="bi bi-graph-up-arrow me-2 text-success"></i>{% trans %}Métricas de Ocupación{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-calendar3 me-1"></i>{% trans %}Cronograma & Reservas{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.calendar_view') }}"><i class="bi bi-calendar-week me-2 text-primary"></i>{% trans %}Calendario General{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.today_schedule') }}"><i class="bi bi-calendar-day me-2 text-info"></i>{% trans %}Cartelera del Día{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.list_reservations') }}"><i class="bi bi-list-check me-2 text-warning"></i>{% trans %}Gestión de Reservas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.add_reservation') }}"><i class="bi bi-plus-circle me-2 text-success"></i>{% trans %}Nueva Reserva{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.commissions_view') }}"><i class="bi bi-diagram-3 me-2 text-primary"></i>{% trans %}Comisiones y Cursadas{% endtrans %}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('genetic_algorithm_web.genetic_optimizer') }}"><i class="bi bi-cpu me-2 text-info"></i>{% trans %}Optimizador de Aulas (IA){% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-mortarboard me-1"></i>{% trans %}Gestión Académica{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.careers_list') }}"><i class="bi bi-mortarboard me-2 text-primary"></i>{% trans %}Carreras{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.subjects_list') }}"><i class="bi bi-book me-2 text-info"></i>{% trans %}Asignaturas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.academic_terms_list') }}"><i class="bi bi-calendar-range me-2 text-warning"></i>{% trans %}Ciclo Lectivo{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-shield-lock me-1"></i>{% trans %}Administración{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.users_list') }}"><i class="bi bi-people me-2 text-primary"></i>{% trans %}Usuarios{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.roles_list') }}"><i class="bi bi-person-badge me-2 text-info"></i>{% trans %}Roles y Permisos RBAC{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.milestone_types_list') }}"><i class="bi bi-tags me-2 text-secondary"></i>{% trans %}Tipificaciones de Hitos{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.google_sheets_import') }}"><i class="bi bi-file-earmark-spreadsheet me-2 text-success"></i>{% trans %}Sincronización Sheets{% endtrans %}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.audit_logs') }}"><i class="bi bi-shield-check me-2 text-warning"></i>{% trans %}Registro de Auditoría{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><hr class="dropdown-divider my-1"></li>
|
||||
<!-- Administración & Sistema -->
|
||||
<li class="dropdown-header text-uppercase small fw-bold text-muted py-1" style="font-size: 0.68rem; letter-spacing: 0.5px;">{% trans %}Administración & Seguridad{% endtrans %}</li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.users_list') }}"><i class="bi bi-people me-2"></i>{% trans %}Usuarios{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.roles_list') }}"><i class="bi bi-person-badge me-2"></i>{% trans %}Roles y Permisos{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.milestone_types_list') }}"><i class="bi bi-tags me-2 text-secondary"></i>{% trans %}Tipificaciones de Hitos{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.google_sheets_import') }}"><i class="bi bi-file-earmark-spreadsheet me-2 text-success"></i>{% trans %}Sincronización Sheets{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% elif user_role == 'bedelia' %}
|
||||
<!-- ================= BEDELÍA NAVIGATION ================= -->
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('main.dashboard') }}">
|
||||
<i class="bi bi-speedometer2 me-1"></i>{% trans %}Panel Bedelía{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-door-open me-1"></i>{% trans %}Espacios & Aulas{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='physical') }}"><i class="bi bi-door-open me-2 text-primary"></i>{% trans %}Aulas Presenciales{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='virtual') }}"><i class="bi bi-camera-video me-2 text-info"></i>{% trans %}Aulas Virtuales (Reunión){% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms') }}"><i class="bi bi-grid me-2 text-secondary"></i>{% trans %}Todas las Aulas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.add_classroom') }}"><i class="bi bi-plus-circle me-2 text-success"></i>{% trans %}Nueva Aula{% endtrans %}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('buildings.list_buildings') }}"><i class="bi bi-buildings me-2 text-secondary"></i>{% trans %}Edificios y Sedes{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.occupancy_metrics') }}"><i class="bi bi-graph-up-arrow me-2 text-success"></i>{% trans %}Métricas de Ocupación{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-calendar3 me-1"></i>{% trans %}Operaciones & Reservas{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.today_schedule') }}"><i class="bi bi-calendar-day me-2 text-info"></i>{% trans %}Cartelera del Día{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.calendar_view') }}"><i class="bi bi-calendar-week me-2 text-primary"></i>{% trans %}Calendario General{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.list_reservations') }}"><i class="bi bi-list-check me-2 text-warning"></i>{% trans %}Gestión de Reservas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.add_reservation') }}"><i class="bi bi-plus-circle me-2 text-success"></i>{% trans %}Registrar Reserva{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.commissions_view') }}"><i class="bi bi-diagram-3 me-2 text-primary"></i>{% trans %}Comisiones y Cursadas{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-mortarboard me-1"></i>{% trans %}Académica & Cursadas{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.careers_list') }}"><i class="bi bi-mortarboard me-2 text-primary"></i>{% trans %}Carreras{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.subjects_list') }}"><i class="bi bi-book me-2 text-info"></i>{% trans %}Asignaturas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.academic_terms_list') }}"><i class="bi bi-calendar-range me-2 text-warning"></i>{% trans %}Ciclo Lectivo{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.milestone_types_list') }}"><i class="bi bi-tags me-2 text-secondary"></i>{% trans %}Tipificaciones de Hitos{% endtrans %}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('admin.google_sheets_import') }}"><i class="bi bi-file-earmark-spreadsheet me-2 text-success"></i>{% trans %}Sincronización Sheets{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
{% elif user_role == 'docente' %}
|
||||
<!-- ================= DOCENTE / PROFESOR NAVIGATION ================= -->
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('main.dashboard') }}">
|
||||
<i class="bi bi-speedometer2 me-1"></i>{% trans %}Panel Docente{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-calendar-check me-1"></i>{% trans %}Mis Clases & Reservas{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.list_reservations') }}"><i class="bi bi-calendar2-check me-2 text-primary"></i>{% trans %}Mis Reservas de Aulas{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.add_reservation') }}"><i class="bi bi-plus-circle me-2 text-success"></i>{% trans %}Solicitar Nueva Reserva{% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.commissions_view') }}"><i class="bi bi-diagram-3 me-2 text-info"></i>{% trans %}Mis Comisiones & Cursadas{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<i class="bi bi-building me-1"></i>{% trans %}Campus & Horarios{% endtrans %}
|
||||
</a>
|
||||
<ul class="dropdown-menu shadow-sm">
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.today_schedule') }}"><i class="bi bi-calendar-day me-2 text-info"></i>{% trans %}Cartelera del Día (¿Dónde curso hoy?){% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('schedule.calendar_view') }}"><i class="bi bi-calendar-week me-2 text-primary"></i>{% trans %}Calendario General de Aulas{% endtrans %}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='virtual') }}"><i class="bi bi-camera-video me-2 text-info"></i>{% trans %}Aulas Virtuales (Reuniones){% endtrans %}</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('classrooms.list_classrooms', view_mode='physical') }}"><i class="bi bi-door-open me-2 text-secondary"></i>{% trans %}Consulta de Aulas Presenciales{% endtrans %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
{% else %}
|
||||
<!-- ================= ALUMNO / ESTUDIANTE NAVIGATION ================= -->
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('main.dashboard') }}">
|
||||
<i class="bi bi-house-door me-1"></i>{% trans %}Mi Portal{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('schedule.today_schedule') }}">
|
||||
<i class="bi bi-geo-alt me-1"></i>{% trans %}Cartelera de Hoy{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('schedule.calendar_view') }}">
|
||||
<i class="bi bi-calendar-week me-1"></i>{% trans %}Cronograma de Clases{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('classrooms.list_classrooms', view_mode='virtual') }}">
|
||||
<i class="bi bi-camera-video me-1"></i>{% trans %}Aulas Virtuales{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('classrooms.list_classrooms', view_mode='physical') }}">
|
||||
<i class="bi bi-door-open me-1"></i>{% trans %}Espacios del Campus{% endtrans %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
@@ -148,17 +227,25 @@
|
||||
{% include 'partials/language_switcher.html' %}
|
||||
</li>
|
||||
|
||||
<!-- User Dropdown with Avatar -->
|
||||
<!-- User Dropdown with Avatar and Institutional Role -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle d-flex align-items-center py-1" href="#" role="button" data-bs-toggle="dropdown">
|
||||
<span class="user-avatar-small">{{ current_user.name[:1]|upper if current_user.name else 'U' }}</span>
|
||||
<span>{{ current_user.first_name }}</span>
|
||||
<div class="d-none d-lg-block text-start ms-2">
|
||||
<div class="lh-1 small fw-semibold">{{ current_user.first_name }}</div>
|
||||
<span class="badge {{ current_user.role_badge_display.class }} role-pill mt-1" style="font-size: 0.65rem; padding: 0.15rem 0.45rem;">
|
||||
<i class="bi {{ current_user.role_badge_display.icon }}"></i> {{ current_user.role_badge_display.label }}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow-sm border-0">
|
||||
<li>
|
||||
<div class="px-3 py-2 border-bottom">
|
||||
<small class="text-muted d-block">{% trans %}Signed in as{% endtrans %}</small>
|
||||
<span class="fw-bold small">{{ current_user.email }}</span>
|
||||
<span class="fw-bold small d-block">{{ current_user.email }}</span>
|
||||
<span class="badge {{ current_user.role_badge_display.class }} role-pill mt-1">
|
||||
<i class="bi {{ current_user.role_badge_display.icon }}"></i> {{ current_user.role_badge_display.label }}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('auth.profile') }}">
|
||||
|
||||
+1055
-244
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user