refactor: Split chat.html into modular JS files
All checks were successful
Botlib CI / build (push) Successful in 12s
Bottest CI / build (push) Successful in 32s
BotUI CI / build (push) Successful in 44s

- chat.html reduced from 1623 lines to 59 lines
- Created chat-switchers.js for switcher state management
- Created chat-messages.js for message rendering
- Created chat-main.js for initialization and coordination
- Added console logging to debug switcher toggle functionality
- Follows AGENTS.md 450-line limit rule
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2026-04-24 16:22:08 +00:00
parent 6ad3ebff00
commit 2d715b2650
4 changed files with 276 additions and 1607 deletions

View file

@ -0,0 +1,97 @@
// Chat Main Module - Initializes chat and coordinates between modules
(function () {
"use strict";
function notify(message, type) {
type = type || "info";
if (window.GBAlerts) {
window.GBAlerts.show(message, type);
} else {
console.log("[" + type + "]", message);
}
}
function initChat() {
console.log("Chat module initialized");
setupEventHandlers();
}
function setupEventHandlers() {
var form = document.getElementById("chatForm");
var input = document.getElementById("messageInput");
if (form) {
form.onsubmit = function (e) {
e.preventDefault();
sendMessage();
return false;
};
}
if (input) {
input.addEventListener("input", handleMentionInput);
}
var scrollBtn = document.getElementById("scrollToBottom");
if (scrollBtn) {
scrollBtn.addEventListener("click", function() {
scrollToBottom(true);
});
}
document.addEventListener("click", function (e) {
if (
!e.target.closest("#mentionDropdown") &&
!e.target.closest("#messageInput")
) {
hideMentionDropdown();
}
});
}
function sendMessage() {
var input = document.getElementById("messageInput");
if (!input) return;
var content = input.value.trim();
if (!content) return;
// Get active switchers
var activeSwitcherIds = getActiveSwitcherIds();
console.log('Sending message with active_switchers:', activeSwitcherIds);
// Add user message
addMessage("user", content);
// Clear input
input.value = "";
input.focus();
// Send via WebSocket
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
bot_id: currentBotId,
user_id: currentUserId,
session_id: currentSessionId,
channel: "web",
content: content,
message_type: MessageType.USER,
active_switchers: activeSwitcherIds,
timestamp: new Date().toISOString()
}));
} else {
notify("Not connected to server. Message not sent.", "warning");
}
}
// Expose to global scope
window.sendMessage = sendMessage;
window.initChat = initChat;
// Initialize on load
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initChat);
} else {
initChat();
}
})();

View file

@ -0,0 +1,53 @@
// Chat Messages Module - Handles message rendering and display
function addMessage(role, content, messageId) {
var messages = document.getElementById("messages");
if (!messages) return;
var messageDiv = document.createElement("div");
messageDiv.className = "message message-" + role;
if (messageId) {
messageDiv.dataset.messageId = messageId;
}
if (role === "bot") {
messageDiv.innerHTML = marked.parse(content);
} else {
messageDiv.textContent = content;
}
messages.appendChild(messageDiv);
scrollToBottom(false);
}
function scrollToBottom(animate) {
var messages = document.getElementById("messages");
if (!messages) return;
if (animate) {
messages.scrollTo({
top: messages.scrollHeight,
behavior: "smooth"
});
} else {
messages.scrollTop = messages.scrollHeight;
}
}
function showThinking() {
var messages = document.getElementById("messages");
if (!messages) return;
var thinking = document.createElement("div");
thinking.className = "message message-bot thinking";
thinking.id = "thinking-indicator";
thinking.textContent = "Thinking...";
messages.appendChild(thinking);
scrollToBottom(false);
}
function hideThinking() {
var thinking = document.getElementById("thinking-indicator");
if (thinking) {
thinking.remove();
}
}

View file

@ -0,0 +1,78 @@
// Chat Switchers Module - Manages format switchers (tables, infographic, cards, etc.)
// This module handles both UI rendering and state management for switchers
var activeSwitchers = new Set();
var switcherDefinitions = [];
function renderBotSwitchers(switchers) {
if (!switchers || switchers.length === 0) return;
var existingIds = {};
switcherDefinitions.forEach(function(sw) { existingIds[sw.id] = true; });
switchers.forEach(function(sw) {
if (!existingIds[sw.id]) {
switcherDefinitions.push({
id: sw.id,
label: sw.label || sw.id,
icon: sw.icon || '🔀',
color: sw.color || '#666'
});
existingIds[sw.id] = true;
}
});
renderSwitchers();
var container = document.getElementById("switchers");
if (container && switcherDefinitions.length > 0) {
container.style.display = '';
}
}
function renderSwitchers() {
var container = document.getElementById("switcherChips");
if (!container) return;
container.innerHTML = switcherDefinitions.map(function(sw) {
var isActive = activeSwitchers.has(sw.id);
return (
'<div class="switcher-chip' + (isActive ? ' active' : '') + '" ' +
'data-switch-id="' + sw.id + '" ' +
'style="--switcher-color: ' + sw.color + '; ' +
(isActive ? 'color: ' + sw.color + ' background: ' + sw.color + '; ' : '') + '">' +
'<span class="switcher-chip-icon">' + sw.icon + '</span>' +
'<span>' + sw.label + '</span>' +
'</div>'
);
}).join('');
container.querySelectorAll('.switcher-chip').forEach(function(chip) {
chip.addEventListener('click', function() {
toggleSwitcher(this.getAttribute('data-switch-id'));
});
});
}
function toggleSwitcher(switcherId) {
console.log('toggleSwitcher called with:', switcherId);
console.log('activeSwitchers before:', Array.from(activeSwitchers));
if (activeSwitchers.has(switcherId)) {
activeSwitchers.delete(switcherId);
console.log('Deleted switcher:', switcherId);
} else {
activeSwitchers.add(switcherId);
console.log('Added switcher:', switcherId);
}
console.log('activeSwitchers after:', Array.from(activeSwitchers));
renderSwitchers();
}
function getActiveSwitcherIds() {
return Array.from(activeSwitchers);
}
function clearSwitchers() {
activeSwitchers.clear();
renderSwitchers();
}

File diff suppressed because it is too large Load diff