Spaces:
Sleeping
Sleeping
Update templates/chat-bot.html
Browse files- templates/chat-bot.html +121 -166
templates/chat-bot.html
CHANGED
|
@@ -1,144 +1,36 @@
|
|
| 1 |
-
<!DOCTYPE html>
|
| 2 |
-
<html lang="es" data-theme="light">
|
| 3 |
-
<head>
|
| 4 |
-
<meta charset="UTF-8">
|
| 5 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>EndoBot - Asistente Dental</title>
|
| 7 |
-
|
| 8 |
-
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 10 |
-
|
| 11 |
-
<style>
|
| 12 |
-
/* Estilos base para scrollbar y compatibilidad */
|
| 13 |
-
body { font-family: 'Inter', sans-serif; -webkit-font-smoothing: antialiased; }
|
| 14 |
-
#chat-messages::-webkit-scrollbar { width: 8px; }
|
| 15 |
-
#chat-messages::-webkit-scrollbar-track { background: #f1f5f9; }
|
| 16 |
-
#chat-messages::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
|
| 17 |
-
#chat-messages::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
|
| 18 |
-
|
| 19 |
-
/* Mantenemos tus variables de color para los modales y el tema oscuro */
|
| 20 |
-
:root {
|
| 21 |
-
--bg-secondary: #ffffff;
|
| 22 |
-
--text-primary: #2c3e50;
|
| 23 |
-
--text-secondary: #6c757d;
|
| 24 |
-
--accent-color: #3498db;
|
| 25 |
-
--border-color: #dee2e6;
|
| 26 |
-
}
|
| 27 |
-
[data-theme="dark"] {
|
| 28 |
-
--bg-secondary: #2c2c2c;
|
| 29 |
-
--text-primary: #e0e0e0;
|
| 30 |
-
--text-secondary: #a0a0a0;
|
| 31 |
-
--accent-color: #87CEEB;
|
| 32 |
-
--border-color: #444;
|
| 33 |
-
}
|
| 34 |
-
|
| 35 |
-
/* Estilos para los modales que no están en Tailwind */
|
| 36 |
-
.modal-overlay {
|
| 37 |
-
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
| 38 |
-
background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(5px);
|
| 39 |
-
display: flex; justify-content: center; align-items: center; z-index: 1000;
|
| 40 |
-
opacity: 0; visibility: hidden; transition: opacity 0.3s, visibility 0.3s;
|
| 41 |
-
}
|
| 42 |
-
.modal-overlay.visible { opacity: 1; visibility: visible; }
|
| 43 |
-
.modal-content {
|
| 44 |
-
background: var(--bg-secondary); padding: 2rem; border-radius: 16px;
|
| 45 |
-
width: 90%; max-width: 700px;
|
| 46 |
-
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
| 47 |
-
transform: scale(0.95); transition: transform 0.3s ease-out;
|
| 48 |
-
}
|
| 49 |
-
.modal-overlay.visible .modal-content { transform: scale(1); }
|
| 50 |
-
.modal-close-button {
|
| 51 |
-
position: absolute; top: 1rem; right: 1rem; background: none; border: none;
|
| 52 |
-
font-size: 1.5rem; color: var(--text-secondary); cursor: pointer;
|
| 53 |
-
width: 40px; height: 40px; border-radius: 50%;
|
| 54 |
-
display: flex; align-items: center; justify-content: center;
|
| 55 |
-
transition: background-color 0.2s, color 0.2s, transform 0.2s;
|
| 56 |
-
}
|
| 57 |
-
.modal-close-button:hover { background-color: #e5e7eb; transform: rotate(90deg); }
|
| 58 |
-
</style>
|
| 59 |
-
</head>
|
| 60 |
-
|
| 61 |
-
<body class="bg-slate-100">
|
| 62 |
-
|
| 63 |
-
<template id="user-message-template">
|
| 64 |
-
<div class="message-wrapper flex items-start gap-3 justify-end">
|
| 65 |
-
<div class="bg-blue-500 text-white p-4 rounded-xl rounded-br-none shadow-md max-w-lg">
|
| 66 |
-
<p class="text-sm message-text-placeholder"></p>
|
| 67 |
-
</div>
|
| 68 |
-
<div class="w-10 h-10 bg-slate-300 text-slate-600 rounded-full flex items-center justify-center flex-shrink-0"><i class="fas fa-user"></i></div>
|
| 69 |
-
</div>
|
| 70 |
-
</template>
|
| 71 |
-
<template id="assistant-message-template">
|
| 72 |
-
<div class="message-wrapper flex items-start gap-3">
|
| 73 |
-
<div class="w-10 h-10 bg-blue-500 text-white rounded-full flex items-center justify-center flex-shrink-0"><i class="fas fa-tooth"></i></div>
|
| 74 |
-
<div class="bg-white p-4 rounded-xl rounded-tl-none shadow-md max-w-2xl border border-slate-200">
|
| 75 |
-
<p class="text-sm text-slate-700 message-text-placeholder"></p>
|
| 76 |
-
</div>
|
| 77 |
-
</div>
|
| 78 |
-
</template>
|
| 79 |
-
|
| 80 |
-
<div class="relative w-full h-screen flex flex-col">
|
| 81 |
-
<header class="bg-blue-600 text-white shadow-md w-full flex-shrink-0 z-10 p-4 flex justify-between items-center">
|
| 82 |
-
<div class="flex items-center gap-3">
|
| 83 |
-
<i class="fas fa-tooth text-2xl"></i>
|
| 84 |
-
<h2 class="font-bold text-xl">EndoBot Asistente</h2>
|
| 85 |
-
</div>
|
| 86 |
-
<div class="flex items-center gap-2">
|
| 87 |
-
<button id="admin-panel-button" class="text-white hover:bg-blue-700 p-2 rounded-full transition-colors" title="Admin Panel"><i class="fas fa-shield-halved"></i></button>
|
| 88 |
-
<button id="theme-toggle" class="text-white hover:bg-blue-700 p-2 rounded-full transition-colors" title="Toggle Theme"><i class="fas fa-moon"></i></button>
|
| 89 |
-
</div>
|
| 90 |
-
</header>
|
| 91 |
-
|
| 92 |
-
<main class="w-full flex-1 flex flex-col overflow-hidden">
|
| 93 |
-
<div id="chat-messages" class="flex-1 p-6 overflow-y-auto space-y-6">
|
| 94 |
-
<div class="flex items-start gap-3">
|
| 95 |
-
<div class="w-10 h-10 bg-blue-500 text-white rounded-full flex items-center justify-center flex-shrink-0"><i class="fas fa-tooth"></i></div>
|
| 96 |
-
<div class="bg-white p-4 rounded-xl rounded-tl-none shadow-md max-w-lg border border-slate-200">
|
| 97 |
-
<p class="text-lg font-bold text-blue-600 mb-2">¡Hola! Soy EndoBot, tu asistente dental.</p>
|
| 98 |
-
<p class="text-sm text-slate-700">Puedo ayudarte con diagnósticos, tratamientos y consultas sobre patologías orales. ¿En qué te puedo ayudar hoy?</p>
|
| 99 |
-
</div>
|
| 100 |
-
</div>
|
| 101 |
-
</div>
|
| 102 |
-
|
| 103 |
-
<div class="bg-white p-4 border-t border-slate-200 flex-shrink-0">
|
| 104 |
-
<form id="chat-form" class="flex items-center gap-3">
|
| 105 |
-
<textarea id="user-input" class="flex-1 bg-slate-100 rounded-lg p-3 border border-transparent focus:outline-none focus:ring-2 focus:ring-blue-500 transition" placeholder="Escribe tu consulta aquí..." rows="1" style="resize: none;" disabled></textarea>
|
| 106 |
-
<button type="submit" id="send-button" class="bg-blue-500 hover:bg-blue-600 text-white rounded-full w-12 h-12 flex items-center justify-center flex-shrink-0 transition-colors shadow-md hover:shadow-lg disabled:bg-slate-400" disabled><i class="fas fa-paper-plane"></i></button>
|
| 107 |
-
</form>
|
| 108 |
-
</div>
|
| 109 |
-
</main>
|
| 110 |
-
</div>
|
| 111 |
-
|
| 112 |
-
<div class="modal-overlay" id="admin-modal-overlay">
|
| 113 |
-
<div class="modal-content">
|
| 114 |
-
<button class="modal-close-button" id="modal-close-btn">×</button>
|
| 115 |
-
<h3><i class="fas fa-cogs"></i> System Control Panel</h3>
|
| 116 |
-
</div>
|
| 117 |
-
</div>
|
| 118 |
-
<div class="modal-overlay" id="credentials-modal">
|
| 119 |
-
<div class="modal-content" style="max-width: 400px;">
|
| 120 |
-
<h3 id="credentials-title">Authentication Required</h3>
|
| 121 |
-
</div>
|
| 122 |
-
</div>
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
| 126 |
-
<script src="https://unpkg.com/autosize@4.0.2/dist/autosize.min.js"></script>
|
| 127 |
-
|
| 128 |
<script>
|
| 129 |
document.addEventListener('DOMContentLoaded', () => {
|
| 130 |
// --- STATE MANAGEMENT (Sin cambios) ---
|
| 131 |
let sessionId = null;
|
| 132 |
let sessionAuth = { admin: null, report: null };
|
| 133 |
|
| 134 |
-
// --- ELEMENT SELECTORS (
|
|
|
|
| 135 |
const ui = {
|
| 136 |
sendButton: document.getElementById('send-button'),
|
| 137 |
userInput: document.getElementById('user-input'),
|
| 138 |
chatMessages: document.getElementById('chat-messages'),
|
| 139 |
themeToggle: document.getElementById('theme-toggle'),
|
| 140 |
adminPanelButton: document.getElementById('admin-panel-button'),
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
};
|
| 143 |
autosize(ui.userInput);
|
| 144 |
|
|
@@ -146,46 +38,52 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 146 |
const applyTheme = (theme) => {
|
| 147 |
document.documentElement.setAttribute('data-theme', theme);
|
| 148 |
localStorage.setItem('chatTheme', theme);
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
};
|
| 151 |
const toggleTheme = () => applyTheme(document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark');
|
| 152 |
|
| 153 |
// --- MODAL MANAGEMENT (Sin cambios) ---
|
| 154 |
-
const toggleModal = (modalOverlay, show) =>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
-
// --- CHAT MESSAGING (
|
| 157 |
const initializeChat = async () => {
|
| 158 |
applyTheme(localStorage.getItem('chatTheme') || 'light');
|
| 159 |
try {
|
| 160 |
-
//
|
| 161 |
// const response = await axios.post('/create-session');
|
| 162 |
// sessionId = response.data.session_id;
|
| 163 |
ui.userInput.disabled = false;
|
| 164 |
ui.sendButton.disabled = false;
|
| 165 |
} catch (error) {
|
| 166 |
console.error('Error creating session:', error);
|
| 167 |
-
// Adaptamos el mensaje de error para que use el nuevo formato
|
| 168 |
appendMessage({sender: 'bot', text: 'Problema al inicial la sesión. Por favor refresca la pagina.'});
|
| 169 |
}
|
| 170 |
};
|
| 171 |
-
|
| 172 |
-
// **MODIFICADO**: Esta función ahora usa las plantillas (templates)
|
| 173 |
const appendMessage = ({ sender, text }) => {
|
| 174 |
const typingIndicator = document.getElementById('typing-indicator');
|
| 175 |
if (typingIndicator) typingIndicator.remove();
|
| 176 |
|
| 177 |
const templateId = sender === 'bot' ? 'assistant-message-template' : 'user-message-template';
|
| 178 |
const template = document.getElementById(templateId);
|
|
|
|
|
|
|
| 179 |
const messageClone = template.content.cloneNode(true);
|
| 180 |
-
|
| 181 |
const messageTextElement = messageClone.querySelector('.message-text-placeholder');
|
| 182 |
-
messageTextElement.textContent = text;
|
| 183 |
|
| 184 |
ui.chatMessages.appendChild(messageClone);
|
| 185 |
ui.chatMessages.scrollTop = ui.chatMessages.scrollHeight;
|
| 186 |
};
|
| 187 |
|
| 188 |
-
// **MODIFICADO**: Indicador de escritura con el nuevo estilo
|
| 189 |
const showTypingIndicator = () => {
|
| 190 |
if (document.getElementById('typing-indicator')) return;
|
| 191 |
const indicatorHTML = `
|
|
@@ -198,7 +96,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 198 |
};
|
| 199 |
|
| 200 |
const sendMessage = async () => {
|
| 201 |
-
// Tu lógica de sendMessage original no necesita cambios
|
| 202 |
const message = ui.userInput.value.trim();
|
| 203 |
if (message === '') return;
|
| 204 |
|
|
@@ -208,39 +105,97 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 208 |
showTypingIndicator();
|
| 209 |
|
| 210 |
try {
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
// Simulación para prueba
|
| 215 |
-
await new Promise(r => setTimeout(r, 1500));
|
| 216 |
-
const cleanResponse = `Esta es una respuesta simulada para: "${message}". El nuevo diseño funciona.`;
|
| 217 |
-
|
| 218 |
appendMessage({sender: 'bot', text: cleanResponse});
|
| 219 |
} catch (error) {
|
| 220 |
console.error('Error sending message:', error);
|
| 221 |
-
appendMessage({sender: 'bot', text: '
|
| 222 |
}
|
| 223 |
};
|
| 224 |
|
| 225 |
-
// --- CREDENTIALS & ADMIN FUNCTIONS (
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
const chatForm = document.getElementById('chat-form');
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
// --- STARTUP ---
|
| 241 |
initializeChat();
|
| 242 |
});
|
| 243 |
-
</script>
|
| 244 |
-
|
| 245 |
-
</body>
|
| 246 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
<script>
|
| 2 |
document.addEventListener('DOMContentLoaded', () => {
|
| 3 |
// --- STATE MANAGEMENT (Sin cambios) ---
|
| 4 |
let sessionId = null;
|
| 5 |
let sessionAuth = { admin: null, report: null };
|
| 6 |
|
| 7 |
+
// --- ELEMENT SELECTORS (COMPLETO) ---
|
| 8 |
+
// Ahora incluimos TODOS los selectores de tu JS original
|
| 9 |
const ui = {
|
| 10 |
sendButton: document.getElementById('send-button'),
|
| 11 |
userInput: document.getElementById('user-input'),
|
| 12 |
chatMessages: document.getElementById('chat-messages'),
|
| 13 |
themeToggle: document.getElementById('theme-toggle'),
|
| 14 |
adminPanelButton: document.getElementById('admin-panel-button'),
|
| 15 |
+
adminModal: {
|
| 16 |
+
overlay: document.getElementById('admin-modal-overlay'),
|
| 17 |
+
closeBtn: document.getElementById('modal-close-btn'),
|
| 18 |
+
rebuildIndexBtn: document.getElementById('rebuild-index-button'),
|
| 19 |
+
clearHistoryBtn: document.getElementById('clear-history-button'),
|
| 20 |
+
downloadDbBtn: document.getElementById('download-db-button'),
|
| 21 |
+
downloadLogBtn: document.getElementById('download-log-button'),
|
| 22 |
+
refreshStatusBtn: document.getElementById('refresh-status-button'),
|
| 23 |
+
changeCredsBtn: document.getElementById('change-credentials-button'),
|
| 24 |
+
statusDisplay: document.getElementById('rag-status-display')
|
| 25 |
+
},
|
| 26 |
+
credsModal: {
|
| 27 |
+
overlay: document.getElementById('credentials-modal'),
|
| 28 |
+
title: document.getElementById('credentials-title'),
|
| 29 |
+
usernameInput: document.getElementById('username-input'),
|
| 30 |
+
passwordInput: document.getElementById('password-input'),
|
| 31 |
+
cancelBtn: document.getElementById('credentials-cancel-btn'),
|
| 32 |
+
submitBtn: document.getElementById('credentials-submit-btn')
|
| 33 |
+
}
|
| 34 |
};
|
| 35 |
autosize(ui.userInput);
|
| 36 |
|
|
|
|
| 38 |
const applyTheme = (theme) => {
|
| 39 |
document.documentElement.setAttribute('data-theme', theme);
|
| 40 |
localStorage.setItem('chatTheme', theme);
|
| 41 |
+
// Pequeño ajuste para que funcione con la estructura del botón
|
| 42 |
+
const icon = ui.themeToggle.querySelector('i');
|
| 43 |
+
if(icon) {
|
| 44 |
+
icon.className = `fas ${theme === 'dark' ? 'fa-sun' : 'fa-moon'}`;
|
| 45 |
+
}
|
| 46 |
};
|
| 47 |
const toggleTheme = () => applyTheme(document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark');
|
| 48 |
|
| 49 |
// --- MODAL MANAGEMENT (Sin cambios) ---
|
| 50 |
+
const toggleModal = (modalOverlay, show) => {
|
| 51 |
+
if (modalOverlay) {
|
| 52 |
+
modalOverlay.classList.toggle('visible', show);
|
| 53 |
+
}
|
| 54 |
+
};
|
| 55 |
|
| 56 |
+
// --- CHAT MESSAGING (Funcional) ---
|
| 57 |
const initializeChat = async () => {
|
| 58 |
applyTheme(localStorage.getItem('chatTheme') || 'light');
|
| 59 |
try {
|
| 60 |
+
// Descomenta estas líneas cuando tu backend esté listo
|
| 61 |
// const response = await axios.post('/create-session');
|
| 62 |
// sessionId = response.data.session_id;
|
| 63 |
ui.userInput.disabled = false;
|
| 64 |
ui.sendButton.disabled = false;
|
| 65 |
} catch (error) {
|
| 66 |
console.error('Error creating session:', error);
|
|
|
|
| 67 |
appendMessage({sender: 'bot', text: 'Problema al inicial la sesión. Por favor refresca la pagina.'});
|
| 68 |
}
|
| 69 |
};
|
| 70 |
+
|
|
|
|
| 71 |
const appendMessage = ({ sender, text }) => {
|
| 72 |
const typingIndicator = document.getElementById('typing-indicator');
|
| 73 |
if (typingIndicator) typingIndicator.remove();
|
| 74 |
|
| 75 |
const templateId = sender === 'bot' ? 'assistant-message-template' : 'user-message-template';
|
| 76 |
const template = document.getElementById(templateId);
|
| 77 |
+
if (!template) return; // Guarda de seguridad
|
| 78 |
+
|
| 79 |
const messageClone = template.content.cloneNode(true);
|
|
|
|
| 80 |
const messageTextElement = messageClone.querySelector('.message-text-placeholder');
|
| 81 |
+
if(messageTextElement) messageTextElement.textContent = text;
|
| 82 |
|
| 83 |
ui.chatMessages.appendChild(messageClone);
|
| 84 |
ui.chatMessages.scrollTop = ui.chatMessages.scrollHeight;
|
| 85 |
};
|
| 86 |
|
|
|
|
| 87 |
const showTypingIndicator = () => {
|
| 88 |
if (document.getElementById('typing-indicator')) return;
|
| 89 |
const indicatorHTML = `
|
|
|
|
| 96 |
};
|
| 97 |
|
| 98 |
const sendMessage = async () => {
|
|
|
|
| 99 |
const message = ui.userInput.value.trim();
|
| 100 |
if (message === '') return;
|
| 101 |
|
|
|
|
| 105 |
showTypingIndicator();
|
| 106 |
|
| 107 |
try {
|
| 108 |
+
const response = await axios.post('/chat-bot', { query: message, session_id: sessionId });
|
| 109 |
+
const cleanResponse = response.data?.answer || 'Perdona, no puedo procesar eso.';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
appendMessage({sender: 'bot', text: cleanResponse});
|
| 111 |
} catch (error) {
|
| 112 |
console.error('Error sending message:', error);
|
| 113 |
+
appendMessage({sender: 'bot', text: 'Ocurrió un error crítico. Por favor, revisa los logs del servidor.'});
|
| 114 |
}
|
| 115 |
};
|
| 116 |
|
| 117 |
+
// --- CREDENTIALS & ADMIN FUNCTIONS (Toda tu lógica original) ---
|
| 118 |
+
const getCredentials = (type) => {
|
| 119 |
+
return new Promise((resolve, reject) => {
|
| 120 |
+
if (sessionAuth[type]) {
|
| 121 |
+
return resolve(sessionAuth[type]);
|
| 122 |
+
}
|
| 123 |
+
if (!ui.credsModal.overlay) {
|
| 124 |
+
return reject(new Error('Modal de credenciales no encontrado'));
|
| 125 |
+
}
|
| 126 |
+
ui.credsModal.title.textContent = `${type.charAt(0).toUpperCase() + type.slice(1)} Authentication`;
|
| 127 |
+
ui.credsModal.usernameInput.value = '';
|
| 128 |
+
ui.credsModal.passwordInput.value = '';
|
| 129 |
+
toggleModal(ui.credsModal.overlay, true);
|
| 130 |
+
ui.credsModal.usernameInput.focus();
|
| 131 |
+
|
| 132 |
+
const handleSubmit = () => {
|
| 133 |
+
const username = ui.credsModal.usernameInput.value;
|
| 134 |
+
const password = ui.credsModal.passwordInput.value;
|
| 135 |
+
cleanup();
|
| 136 |
+
if (username && password) {
|
| 137 |
+
resolve({ username, password });
|
| 138 |
+
} else {
|
| 139 |
+
reject(new Error('Credentials not provided.'));
|
| 140 |
+
}
|
| 141 |
+
};
|
| 142 |
+
|
| 143 |
+
const handleCancel = () => {
|
| 144 |
+
cleanup();
|
| 145 |
+
reject(new Error('Authentication cancelled.'));
|
| 146 |
+
};
|
| 147 |
+
|
| 148 |
+
const cleanup = () => {
|
| 149 |
+
ui.credsModal.submitBtn.removeEventListener('click', handleSubmit);
|
| 150 |
+
ui.credsModal.cancelBtn.removeEventListener('click', handleCancel);
|
| 151 |
+
toggleModal(ui.credsModal.overlay, false);
|
| 152 |
+
};
|
| 153 |
+
|
| 154 |
+
ui.credsModal.submitBtn.addEventListener('click', handleSubmit);
|
| 155 |
+
ui.credsModal.cancelBtn.addEventListener('click', handleCancel);
|
| 156 |
+
});
|
| 157 |
+
};
|
| 158 |
+
// ... Aquí irían tus otras funciones de admin como forceRebuildIndex, downloadFile, etc...
|
| 159 |
+
|
| 160 |
+
// --- EVENT LISTENERS (AHORA COMPLETOS) ---
|
| 161 |
const chatForm = document.getElementById('chat-form');
|
| 162 |
+
if (chatForm) {
|
| 163 |
+
chatForm.addEventListener('submit', (e) => {
|
| 164 |
+
e.preventDefault();
|
| 165 |
+
sendMessage();
|
| 166 |
+
});
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
if(ui.userInput) {
|
| 170 |
+
ui.userInput.addEventListener('keypress', (e) => e.key === 'Enter' && !e.shiftKey && (e.preventDefault(), sendMessage()));
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
// ¡AQUÍ ESTÁ LA MAGIA! Conectamos los botones.
|
| 174 |
+
if(ui.themeToggle) {
|
| 175 |
+
ui.themeToggle.addEventListener('click', toggleTheme);
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
if(ui.adminPanelButton) {
|
| 179 |
+
ui.adminPanelButton.addEventListener('click', () => toggleModal(ui.adminModal.overlay, true));
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
if(ui.adminModal.closeBtn) {
|
| 183 |
+
ui.adminModal.closeBtn.addEventListener('click', () => toggleModal(ui.adminModal.overlay, false));
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
if(ui.adminModal.overlay) {
|
| 187 |
+
ui.adminModal.overlay.addEventListener('click', (e) => {
|
| 188 |
+
if (e.target === ui.adminModal.overlay) {
|
| 189 |
+
toggleModal(ui.adminModal.overlay, false);
|
| 190 |
+
}
|
| 191 |
+
});
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
// ... Aquí irían el resto de tus listeners para los botones del modal de admin ...
|
| 195 |
+
// ui.adminModal.rebuildIndexBtn.addEventListener(...)
|
| 196 |
+
// etc.
|
| 197 |
+
|
| 198 |
// --- STARTUP ---
|
| 199 |
initializeChat();
|
| 200 |
});
|
| 201 |
+
</script>
|
|
|
|
|
|
|
|
|