312 lines
12 KiB
HTML
312 lines
12 KiB
HTML
{% load static %}
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
|
<meta name="author" content="Maom">
|
|
<title>{% block titulo %}Servicio de Transporte{% endblock %}</title>
|
|
<link rel="icon" href="{% static 'img/transporte.ico' %}" type="image/x-icon">
|
|
|
|
<!-- Fonts and Icons -->
|
|
<link rel="stylesheet" href="{% static 'assets/fonts/iconos/css/all.min.css' %}" />
|
|
<!-- En tu archivo base.html -->
|
|
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> -->
|
|
|
|
<!-- CSS Files -->
|
|
<link rel="stylesheet" href="{% static 'assets/css/select2.min.css' %}" />
|
|
<link rel="stylesheet" href="{% static 'assets/css/bootstrap.min.css' %}">
|
|
<link rel="stylesheet" href="{% static 'assets/css/plugins.min.css' %}">
|
|
<link rel="stylesheet" href="{% static 'assets/css/kaiadmin.min.css' %}">
|
|
<link rel="stylesheet" href="{% static 'assets/css/animate.min.css' %}" />
|
|
|
|
<style>
|
|
body { transition: background-color 0.3s, color 0.3s; font-family: 'Poppins', sans-serif; }
|
|
.dark-mode { background-color: #1a2035; color: #ffffff; }
|
|
.dark-mode .main-panel { background-color: #1a2035; }
|
|
.dark-mode .card { background-color: #2f3545; color: #ffffff; }
|
|
.dark-mode .table-dark { background-color: #2f3545; }
|
|
.dark-mode .badge.bg-dark { background-color: #ffffff !important; color: #000000 !important; }
|
|
.page-inner { animation: fadeIn 0.5s ease-in; padding: 20px; }
|
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
.card { border-radius: 15px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); transition: transform 0.3s ease; }
|
|
.card:hover { transform: translateY(-5px); }
|
|
|
|
|
|
.form-control:focus {
|
|
border-color: #0d6efd;
|
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
|
}
|
|
.card { border-radius: 15px; }
|
|
.card-header { border-radius: 15px 15px 0 0 !important; }
|
|
</style>
|
|
|
|
{% block css %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<div class="wrapper" id="contenido">
|
|
<div class="modal fade" id="logoutWarning" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Sesión por expirar</h5>
|
|
</div>
|
|
<div class="modal-body">
|
|
La sesión se cerrará en <span id="countdown">{{ warning_time }}</span> segundos.
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" onclick="resetTimer()">Continuar</button>
|
|
<button type="button" class="btn btn-primary" onclick="logoutUser()">Cerrar ahora</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% block vertical %}{% include 'partes/vertical.html' %}{% endblock %}
|
|
<div class="main-panel">
|
|
{% block horizontal %}{% include 'partes/horizontal.html' %}{% endblock %}
|
|
<div class="container">
|
|
<div class="page-inner" id="page-content">
|
|
{% block seccion %}{% endblock %}
|
|
{% block contenido %}{% endblock %}
|
|
</div>
|
|
</div>
|
|
{% block pie %}{% include 'partes/pie.html' %}{% endblock %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Core JS Files -->
|
|
<script src="{% static 'assets/js/core/jquery-3.7.1.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/core/popper.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/core/bootstrap.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/plugin/datatables/datatables.min.js' %}"></script>
|
|
|
|
<!-- Plugin JS Files -->
|
|
<script src="{% static 'assets/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/plugin/jquery.sparkline/jquery.sparkline.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/plugin/bootstrap-notify/bootstrap-notify.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/plugin/jsvectormap/jsvectormap.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/plugin/jsvectormap/world.js' %}"></script>
|
|
<script src="{% static 'assets/js/sweetalert211.js' %}"></script>
|
|
|
|
<!-- Chart JS -->
|
|
<script src="{% static 'assets/js/plugin/chart.js/chart.min.js' %}"></script>
|
|
|
|
<!-- Kaiadmin JS -->
|
|
<script src="{% static 'assets/js/kaiadmin.min.js' %}"></script>
|
|
<script src="{% static 'assets/js/select2.min.js' %}"></script>
|
|
|
|
<!-- Pasar mensajes de Django a JavaScript como atributo data -->
|
|
<div id="django-messages" data-messages='[
|
|
{% if messages %}
|
|
{% for message in messages %}
|
|
{"tags": "{{ message.tags }}", "text": "{{ message | escapejs }}"},
|
|
{% endfor %}
|
|
{% endif %}
|
|
]'>
|
|
</div>
|
|
|
|
|
|
<!-- Script personalizado global -->
|
|
<script>
|
|
// Definir función global al inicio
|
|
|
|
window.loadPageContent = function(url, pushState = true) {
|
|
console.log('Iniciando loadPageContent con URL:', url);
|
|
fetch(url, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
|
|
.then(response => {
|
|
console.log('Respuesta recibida:', response.status);
|
|
if (!response.ok) throw new Error('Network response was not ok');
|
|
return response.text();
|
|
})
|
|
.then(html => {
|
|
console.log('HTML recibido:', html.substring(0, 100));
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(html, 'text/html');
|
|
// Extraer solo el contenido interno de #page-content si existe, o el body completo
|
|
const newContentElement = doc.querySelector('#page-content') || doc.body;
|
|
const newContent = newContentElement.innerHTML;
|
|
const pageContent = document.getElementById('page-content');
|
|
if (pageContent) {
|
|
pageContent.innerHTML = newContent; // Reemplazar solo el contenido interno
|
|
console.log('Contenido cargado en #page-content');
|
|
window.reinitializeScripts(); // Re-inicializar scripts después de cargar
|
|
} else {
|
|
console.error('No se encontró #page-content en el DOM');
|
|
}
|
|
if (pushState) window.history.pushState({ url: url }, document.title, url);
|
|
})
|
|
.catch(error => console.error('Error en loadPageContent:', error));
|
|
};
|
|
|
|
|
|
function reinitializeScripts() {
|
|
if (typeof $.fn.select2 !== 'undefined') {
|
|
$('.select2').select2({ theme: 'bootstrap4', width: '100%' });
|
|
}
|
|
initializeCustomTables();
|
|
if (typeof bootstrap !== 'undefined') {
|
|
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => new bootstrap.Tooltip(el));
|
|
}
|
|
}
|
|
|
|
|
|
// Ejecutar después de cargar el DOM
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// Tema oscuro
|
|
const toggleDarkMode = () => {
|
|
document.body.classList.toggle('dark-mode');
|
|
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
|
|
};
|
|
if (localStorage.getItem('darkMode') === 'true') {
|
|
document.body.classList.add('dark-mode');
|
|
}
|
|
document.getElementById('darkModeToggle')?.addEventListener('click', toggleDarkMode);
|
|
|
|
// Obtener mensajes desde el atributo data-messages
|
|
const messagesContainer = document.getElementById('django-messages');
|
|
let djangoMessages = [];
|
|
if (messagesContainer && messagesContainer.getAttribute('data-messages')) {
|
|
const messagesStr = messagesContainer.getAttribute('data-messages').replace(/,\s*]/, ']');
|
|
djangoMessages = JSON.parse(messagesStr);
|
|
}
|
|
|
|
// Mostrar mensajes con SweetAlert2
|
|
if (djangoMessages.length > 0) {
|
|
const Toast = Swal.mixin({
|
|
toast: true,
|
|
position: "top-end",
|
|
showConfirmButton: false,
|
|
timer: 3000,
|
|
timerProgressBar: true,
|
|
didOpen: (toast) => {
|
|
toast.onmouseenter = Swal.stopTimer;
|
|
toast.onmouseleave = Swal.resumeTimer;
|
|
},
|
|
background: document.body.classList.contains('dark-mode') ? '#2f3545' : '#fff',
|
|
color: document.body.classList.contains('dark-mode') ? '#fff' : '#000'
|
|
});
|
|
|
|
|
|
djangoMessages.forEach(message => {
|
|
Toast.fire({
|
|
icon: message.tags,
|
|
title: message.text,
|
|
customClass: { popup: 'animate__animated animate__fadeInDown' }
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const inputs = document.querySelectorAll('.form-control:not([type="number"])');
|
|
inputs.forEach(input => {
|
|
input.addEventListener('input', function() {
|
|
this.value = this.value.toUpperCase();
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
// Configuraciones de tiempo
|
|
const SESSION_TIMEOUT = parseInt("{{ session_timeout|default:1800 }}") * 1000; // 30 min
|
|
const WARNING_TIME = parseInt("{{ warning_time|default:300 }}") * 1000; // 5 min
|
|
|
|
// Variables de control
|
|
let timer;
|
|
let warningTimer;
|
|
let countdownInterval;
|
|
let isLoggingOut = false;
|
|
let modalVisible = false; // Nueva variable para controlar estado del modal
|
|
|
|
function resetTimer(forceReset = false) {
|
|
// Solo reiniciar si el modal no está visible o forzado
|
|
if (!modalVisible || forceReset) {
|
|
clearTimeout(timer);
|
|
clearTimeout(warningTimer);
|
|
clearInterval(countdownInterval);
|
|
$('#logoutWarning').modal('hide');
|
|
modalVisible = false;
|
|
|
|
warningTimer = setTimeout(() => {
|
|
$('#logoutWarning').modal('show');
|
|
modalVisible = true;
|
|
startCountdown();
|
|
}, SESSION_TIMEOUT - WARNING_TIME);
|
|
|
|
timer = setTimeout(logoutUser, SESSION_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
function startCountdown() {
|
|
let seconds = Math.floor(WARNING_TIME / 1000);
|
|
const countdownElement = document.getElementById('countdown');
|
|
countdownElement.textContent = seconds;
|
|
|
|
countdownInterval = setInterval(() => {
|
|
seconds--;
|
|
countdownElement.textContent = seconds;
|
|
if (seconds <= 0) {
|
|
clearInterval(countdownInterval);
|
|
logoutUser();
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
// Función de logout (sin cambios)
|
|
function logoutUser() {
|
|
if (isLoggingOut) return;
|
|
isLoggingOut = true;
|
|
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = "{% url 'logout' %}";
|
|
|
|
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
|
|
const csrfInput = document.createElement('input');
|
|
csrfInput.type = 'hidden';
|
|
csrfInput.name = 'csrfmiddlewaretoken';
|
|
csrfInput.value = csrfToken;
|
|
|
|
form.appendChild(csrfInput);
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
// ... (tu código existente de temas y mensajes)
|
|
|
|
// Modificar el event listener para ignorar actividad cuando el modal está visible
|
|
const events = ['mousemove', 'keydown', 'click', 'scroll'];
|
|
events.forEach(e => window.addEventListener(e, () => {
|
|
if (!modalVisible) { // Solo resetear si el modal NO está visible
|
|
resetTimer();
|
|
}
|
|
}));
|
|
|
|
// Manejar el cierre del modal
|
|
$('#logoutWarning').on('hide.bs.modal', function () {
|
|
modalVisible = false;
|
|
});
|
|
|
|
// Iniciar temporizador
|
|
resetTimer();
|
|
|
|
// Botón continuar
|
|
document.querySelector('.btn-secondary')?.addEventListener('click', () => resetTimer(true));
|
|
});
|
|
</script>
|
|
{% block js %}{% endblock %}
|
|
|
|
</body>
|
|
</html> |