275 lines
10 KiB
JavaScript
275 lines
10 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';
|
|
|
|
// Dependencies
|
|
import { createApp, version } from 'vue';
|
|
import { marked } from 'marked';
|
|
|
|
// Import LanguageProvider for sidebar translation support
|
|
import { createLanguageProvider, LANGUAGE_PROVIDER_KEY } from '../../../eveai_chat_client/static/assets/js/services/LanguageProvider.js';
|
|
|
|
// Vue en andere bibliotheken beschikbaar maken
|
|
window.Vue = { createApp, version };
|
|
window.marked = marked;
|
|
|
|
// 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';
|
|
import ChatRoot from '../../../eveai_chat_client/static/assets/vue-components/ChatRoot.vue';
|
|
import DesktopChatShell from '../../../eveai_chat_client/static/assets/vue-components/DesktopChatShell.vue';
|
|
import MobileChatShell from '../../../eveai_chat_client/static/assets/vue-components/MobileChatShell.vue';
|
|
import SideBar from '../../../eveai_chat_client/static/assets/vue-components/SideBar.vue';
|
|
|
|
// VueUse-setup voor de chatclient (maakt composables beschikbaar via window.VueUse)
|
|
import './vueuse-setup.js';
|
|
|
|
// 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 = {};
|
|
}
|
|
|
|
// Initialiseer sidebar (vervangt fillSidebarExplanation en initializeLanguageSelector)
|
|
initializeSidebar();
|
|
|
|
// Initialiseer chat app (simpel)
|
|
initializeChatApp();
|
|
});
|
|
|
|
/**
|
|
* Initialiseert de sidebar component
|
|
*/
|
|
function initializeSidebar() {
|
|
const container = document.getElementById('sidebar-container');
|
|
|
|
if (!container) {
|
|
console.error('#sidebar-container niet gevonden');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Maak props voor de component
|
|
const props = {
|
|
tenantMake: {
|
|
name: window.chatConfig.tenantMake?.name || '',
|
|
logo_url: window.chatConfig.tenantMake?.logo_url || '',
|
|
subtitle: window.chatConfig.tenantMake?.subtitle || ''
|
|
},
|
|
explanationText: window.chatConfig.explanation || '',
|
|
initialLanguage: window.chatConfig.language || 'nl',
|
|
supportedLanguageDetails: window.chatConfig.supportedLanguageDetails || {},
|
|
allowedLanguages: window.chatConfig.allowedLanguages || ['nl', 'en', 'fr', 'de'],
|
|
apiPrefix: window.chatConfig.apiPrefix || ''
|
|
};
|
|
|
|
// Mount de component
|
|
const app = createApp(SideBar, props);
|
|
|
|
// Create and provide LanguageProvider for sidebar components
|
|
const initialLanguage = window.chatConfig?.language || 'nl';
|
|
const apiPrefix = window.chatConfig?.apiPrefix || '';
|
|
const languageProvider = createLanguageProvider(initialLanguage, apiPrefix);
|
|
app.provide(LANGUAGE_PROVIDER_KEY, languageProvider);
|
|
|
|
// Error handler
|
|
app.config.errorHandler = (err, vm, info) => {
|
|
console.error('🚨 [Vue Error in Sidebar]', err);
|
|
console.error('Component:', vm);
|
|
console.error('Error Info:', info);
|
|
};
|
|
|
|
const mountedApp = app.mount(container);
|
|
|
|
// Listen to language change events and update the sidebar's language provider
|
|
const languageChangeHandler = (event) => {
|
|
if (event.detail && event.detail.language) {
|
|
console.log('Sidebar: Received language change event:', event.detail.language);
|
|
languageProvider.setLanguage(event.detail.language);
|
|
}
|
|
};
|
|
document.addEventListener('language-changed', languageChangeHandler);
|
|
|
|
// Store the handler for cleanup if needed
|
|
mountedApp._languageChangeHandler = languageChangeHandler;
|
|
|
|
console.log('✅ Sidebar component successfully mounted with LanguageProvider');
|
|
return mountedApp;
|
|
} catch (error) {
|
|
console.error('🚨 [CRITICAL ERROR] Bij initialiseren sidebar:', error);
|
|
}
|
|
}
|
|
|
|
// initializeMobileHeader is verwijderd; de mobiele header wordt nu volledig
|
|
// binnen ChatApp.vue beheerd.
|
|
|
|
/**
|
|
* 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 {
|
|
// 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 shells / CoreChatApp
|
|
const baseProps = {
|
|
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'],
|
|
tenantName: (window.chatConfig.tenantMake && window.chatConfig.tenantMake.name) || 'EveAI',
|
|
tenantSubtitle: (window.chatConfig.tenantMake && window.chatConfig.tenantMake.subtitle) || '',
|
|
tenantLogoUrl: (window.chatConfig.tenantMake && window.chatConfig.tenantMake.logo_url) || '',
|
|
explanationText: window.chatConfig.explanation || '',
|
|
settings: window.chatConfig.settings || {}
|
|
};
|
|
|
|
// Bepaal shell-type: expliciete config heeft voorrang, anders breakpoint
|
|
const layoutMode = window.chatConfig.layoutMode || 'auto';
|
|
const isMobileBreakpoint = window.innerWidth <= 768;
|
|
let ShellComponent;
|
|
|
|
if (layoutMode === 'desktop') {
|
|
ShellComponent = DesktopChatShell;
|
|
} else if (layoutMode === 'mobile') {
|
|
ShellComponent = MobileChatShell;
|
|
} else {
|
|
ShellComponent = isMobileBreakpoint ? MobileChatShell : DesktopChatShell;
|
|
}
|
|
|
|
const props = { shellComponent: ShellComponent, shellProps: baseProps };
|
|
|
|
// Mount de component via ChatRoot zodat SafeViewport de layout kan beheren
|
|
const app = createApp(ChatRoot, 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.'); |