Files
eveAI/nginx/frontend_src/js/chat-client.js
2025-07-20 11:36:00 +02:00

268 lines
9.2 KiB
JavaScript

// CSS imports
import '../css/chat-client.css';
import '../../../eveai_chat_client/static/assets/css/chat.css';
import '../../../eveai_chat_client/static/assets/css/chat-components.css';
import '../../../eveai_chat_client/static/assets/css/chat-input.css';
import '../../../eveai_chat_client/static/assets/css/chat-message.css';
import '../../../eveai_chat_client/static/assets/css/form.css';
import '../../../eveai_chat_client/static/assets/css/form-message.css';
import '../../../eveai_chat_client/static/assets/css/language-selector.css';
// Dependencies
import { createApp, version } from 'vue';
import { marked } from 'marked';
import { FormField } from '../../../../../../../../../Users/josako/Library/Application Support/JetBrains/PyCharm2025.1/scratches/old js files/FormField.js';
// Vue en andere bibliotheken beschikbaar maken
window.Vue = { createApp, version };
window.marked = marked;
// Support tools
import '../../../eveai_chat_client/static/assets/js/iconManager.js';
import '../../../eveai_chat_client/static/assets/js/translation.js';
// Gebruik barrel export voor componenten
import * as Components from '../../../eveai_chat_client/static/assets/vue-components/index.js';
// Maak Components globaal beschikbaar voor debugging
window.Components = Components;
console.log('Components loaded:', Object.keys(Components));
// Import specifieke componenten
import LanguageSelector from '../../../eveai_chat_client/static/assets/vue-components/LanguageSelector.vue';
import ChatApp from '../../../eveai_chat_client/static/assets/vue-components/ChatApp.vue';
// Globale Vue error tracking
window.addEventListener('error', function(event) {
console.error('🚨 [Global Error]', event.error);
});
// Wacht tot DOM geladen is
document.addEventListener('DOMContentLoaded', function() {
// Controleer of chatConfig is ingesteld
if (!window.chatConfig) {
console.error('chatConfig is niet beschikbaar');
window.chatConfig = {};
}
// Vul de sidebar explanation in
fillSidebarExplanation();
// Initialiseer language selector
initializeLanguageSelector();
// Initialiseer chat app (simpel)
initializeChatApp();
});
/**
* Vul de sidebar explanation in
*/
function fillSidebarExplanation() {
const sidebarElement = document.getElementById('sidebar-explanation');
if (sidebarElement && window.chatConfig.explanation) {
if (typeof window.marked === 'function') {
sidebarElement.innerHTML = window.marked(window.chatConfig.explanation);
} else if (window.marked && typeof window.marked.parse === 'function') {
sidebarElement.innerHTML = window.marked.parse(window.chatConfig.explanation.replace(/\[\[(.*?)\]\]/g, '<strong>$1</strong>'));
} else {
sidebarElement.innerHTML = window.chatConfig.explanation;
}
}
}
/**
* Initialiseert de language selector
*/
function initializeLanguageSelector() {
const container = document.getElementById('language-selector-container');
if (!container) {
console.error('#language-selector-container niet gevonden');
return;
}
try {
// Maak props voor de component
const props = {
initialLanguage: window.chatConfig.language || 'nl',
supportedLanguageDetails: window.chatConfig.supportedLanguageDetails || {},
allowedLanguages: window.chatConfig.allowedLanguages || ['nl', 'en', 'fr', 'de']
};
// Mount de component direct - BELANGRIJK: we gebruiken window.Vue als dat beschikbaar is
// Dit is nodig voor compatibiliteit met oude code
const app = window.Vue && typeof window.Vue.createApp === 'function'
? window.Vue.createApp(LanguageSelector, props)
: createApp(LanguageSelector, props);
// Registreer error handler
app.config.errorHandler = (err, vm, info) => {
console.error('🚨 [Vue Error]', err);
console.error('Component:', vm);
console.error('Error Info:', info);
};
// Mount de component
const mountedApp = app.mount(container);
// Language change event listener
document.addEventListener('vue:language-changed', function(event) {
const newLanguage = event.detail.language;
console.log(`Taal gewijzigd naar ${newLanguage}`);
// Update chatConfig
if (window.chatConfig) {
window.chatConfig.language = newLanguage;
}
// Stuur event voor andere componenten
const globalEvent = new CustomEvent('language-changed', {
detail: { language: newLanguage }
});
document.dispatchEvent(globalEvent);
// Sla voorkeur op
localStorage.setItem('preferredLanguage', newLanguage);
});
} catch (error) {
console.error('🚨 [CRITICAL ERROR] Bij initialiseren language selector:', error);
console.error('Stack trace:', error.stack);
}
}
/**
* Initialiseert de chat app (Vue component)
*/
function initializeChatApp() {
const container = document.querySelector('.chat-container');
if (!container) {
console.error('🚨 [CRITICAL ERROR] .chat-container niet gevonden');
return;
}
try {
if (!ChatApp) {
throw new Error('🚨 [CRITICAL ERROR] ChatApp component niet gevonden');
}
// Extra verificatie dat alle sub-componenten beschikbaar zijn
if (!Components.MessageHistory || !Components.ChatInput ||
!Components.TypingIndicator || !Components.ChatMessage) {
console.warn('⚠️ [WARN] Niet alle benodigde sub-componenten zijn geladen!');
}
// Maak props voor de component
const props = {
apiPrefix: window.chatConfig.apiPrefix || '',
conversationId: window.chatConfig.conversationId || 'default',
userId: window.chatConfig.userId || null,
userName: window.chatConfig.userName || '',
initialLanguage: window.chatConfig.language || 'nl',
supportedLanguageDetails: window.chatConfig.supportedLanguageDetails || {},
allowedLanguages: window.chatConfig.allowedLanguages || ['nl', 'en', 'fr', 'de']
};
// Mount de component met alle nodige componenten
const app = createApp(ChatApp, props);
// SSE verbinding configuratie - injecteren in ChatApp component
app.provide('sseConfig', {
maxRetries: 3,
retryDelay: 2000,
handleSseError: function(error, taskId) {
console.warn(`SSE verbinding voor task ${taskId} mislukt:`, error);
// Fallback naar polling als SSE faalt
return this.fallbackToPolling(taskId);
},
fallbackToPolling: function(taskId) {
console.log(`Fallback naar polling voor task ${taskId}`);
// Polling implementatie - elke 3 seconden status checken
const pollingInterval = setInterval(() => {
const endpoint = `${props.apiPrefix}/api/task_status/${taskId}`;
fetch(endpoint)
.then(response => {
if (!response.ok) throw new Error(`Task status endpoint error: ${response.status}`);
return response.json();
})
.then(data => {
// Dispatch event om dezelfde event interface als SSE te behouden
const mockEvent = new CustomEvent('message', {
detail: { data: JSON.stringify(data) }
});
document.dispatchEvent(new CustomEvent(`sse:${taskId}:message`, { detail: mockEvent }));
// Stop polling als taak klaar is
if (data.status === 'completed' || data.status === 'failed' || data.status === 'cancelled') {
clearInterval(pollingInterval);
}
})
.catch(err => console.error('Polling error:', err));
}, 3000);
return pollingInterval;
}
});
// Registreer alle componenten globaal
Object.entries(Components).forEach(([name, component]) => {
app.component(name, component);
});
// Registreer error handler
app.config.errorHandler = (err, vm, info) => {
console.error('🚨 [Vue Error in ChatApp]', err);
console.error('Component:', vm);
console.error('Error Info:', info);
};
// Mount de component
const mountedApp = app.mount(container);
// Bewaar referentie globaal voor debugging
window.__chatApp = mountedApp;
// Bewaar een referentie naar de Vue instantie voor gebruik door andere componenten
window.__vueApp = app;
} catch (error) {
console.error('🚨 [CRITICAL ERROR] Bij initialiseren chat app:', error);
console.error('Stack trace:', error.stack);
// Fallback naar placeholder
container.innerHTML = '<div>Fout bij het initialiseren van de chat applicatie</div>';
}
}
/**
* Helper functie om Vue 3 element refs te verwerken
* Oplossing voor $el.querySelector problemen
*/
window.getElementFromRef = function(ref) {
if (!ref) return null;
// Vue 3 refs zijn reactieve objecten met een .value eigenschap
if (ref.value && ref.value instanceof HTMLElement) {
return ref.value;
}
// Directe HTML element refs
if (ref instanceof HTMLElement) {
return ref;
}
// Vue 3 component instance (geen $el meer in Vue 3)
if (ref.$el && ref.$el instanceof HTMLElement) {
return ref.$el;
}
// Voor template refs van Vue 3 mounted componenten
if (typeof ref === 'object' && ref !== null) {
const element = ref.el || ref.$el || ref.value;
if (element instanceof HTMLElement) {
return element;
}
}
return null;
}
console.log('Chat client modules geladen en gebundeld met moderne ES module structuur.');