Enhance embedded ChatGPT assistant functionality: Integrate a new chat interface within the index.html template, allowing users to interact with the assistant directly. Update main.js to ensure proper initialization and reference management. Improve user experience with quick query buttons and a responsive chat layout, while maintaining existing functionality in the application.
This commit is contained in:
Binary file not shown.
@@ -40,8 +40,8 @@ const MindMap = {
|
||||
// Initialisiere den ChatGPT-Assistenten
|
||||
const assistant = new ChatGPTAssistant();
|
||||
assistant.init();
|
||||
// Speichere globale Referenz
|
||||
window.chatAssistant = assistant;
|
||||
// Speichere als Teil von MindMap
|
||||
this.assistant = assistant;
|
||||
|
||||
// Seiten-spezifische Initialisierer aufrufen
|
||||
if (this.currentPage && this.pageInitializers[this.currentPage]) {
|
||||
|
||||
@@ -195,6 +195,14 @@
|
||||
: '{{ 'nav-link-light-active' if request.endpoint == 'search_thoughts_page' else 'nav-link-light' }}'">
|
||||
<i class="fa-solid fa-search mr-2"></i>Suche
|
||||
</a>
|
||||
<!-- KI-Assistent Button -->
|
||||
<button onclick="window.MindMap && window.MindMap.assistant && window.MindMap.assistant.toggleAssistant(true)"
|
||||
class="nav-link flex items-center"
|
||||
x-bind:class="darkMode
|
||||
? 'bg-gradient-to-r from-purple-600/80 to-blue-500/80 text-white font-medium px-4 py-2 rounded-xl hover:shadow-lg transition-all duration-300 hover:-translate-y-0.5'
|
||||
: 'bg-gradient-to-r from-purple-500/20 to-blue-400/20 text-gray-800 font-medium px-4 py-2 rounded-xl hover:shadow-md transition-all duration-300 hover:-translate-y-0.5'">
|
||||
<i class="fa-solid fa-robot mr-2"></i>KI-Chat
|
||||
</button>
|
||||
{% if current_user.is_authenticated %}
|
||||
<a href="{{ url_for('profile') }}"
|
||||
class="nav-link flex items-center"
|
||||
@@ -348,6 +356,14 @@
|
||||
: '{{ 'bg-purple-500/10 text-gray-900' if request.endpoint == 'search_thoughts_page' else 'text-gray-700 hover:bg-gray-100 hover:text-gray-900' }}'">
|
||||
<i class="fa-solid fa-search w-5 mr-3"></i>Suche
|
||||
</a>
|
||||
<!-- KI-Button für Mobilmenü -->
|
||||
<button onclick="window.MindMap && window.MindMap.assistant && window.MindMap.assistant.toggleAssistant(true); mobileMenuOpen = false;"
|
||||
class="block w-full text-left py-3.5 px-4 rounded-xl transition-all duration-200 flex items-center"
|
||||
x-bind:class="darkMode
|
||||
? 'bg-gradient-to-r from-purple-600/30 to-blue-500/30 text-white hover:from-purple-600/40 hover:to-blue-500/40'
|
||||
: 'bg-gradient-to-r from-purple-500/10 to-blue-400/10 text-gray-900 hover:from-purple-500/20 hover:to-blue-400/20'">
|
||||
<i class="fa-solid fa-robot w-5 mr-3"></i>KI-Chat
|
||||
</button>
|
||||
{% if current_user.is_authenticated %}
|
||||
<a href="{{ url_for('profile') }}"
|
||||
class="block py-3.5 px-4 rounded-xl transition-all duration-200 flex items-center"
|
||||
@@ -486,5 +502,27 @@
|
||||
|
||||
<!-- Hilfsscripts -->
|
||||
{% block scripts %}{% endblock %}
|
||||
|
||||
<!-- KI-Chat Initialisierung -->
|
||||
<script type="module">
|
||||
// Importiere und initialisiere den ChatGPT-Assistenten direkt, um sicherzustellen,
|
||||
// dass er auf jeder Seite verfügbar ist, selbst wenn MindMap nicht geladen ist
|
||||
import ChatGPTAssistant from "{{ url_for('static', filename='js/modules/chatgpt-assistant.js') }}";
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Prüfen, ob der Assistent bereits durch MindMap initialisiert wurde
|
||||
if (!window.MindMap || !window.MindMap.assistant) {
|
||||
console.log('KI-Assistent wird direkt initialisiert...');
|
||||
const assistant = new ChatGPTAssistant();
|
||||
assistant.init();
|
||||
|
||||
// Speichere in window.MindMap, falls es existiert, oder erstelle es
|
||||
if (!window.MindMap) {
|
||||
window.MindMap = {};
|
||||
}
|
||||
window.MindMap.assistant = assistant;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -342,61 +342,206 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- KI-Assistent mit verbessertem Design -->
|
||||
<div class="glass-morphism p-6 sm:p-8 rounded-3xl transition-all duration-500 hover:-translate-y-3 hover:shadow-xl backdrop-blur-md border border-white/10">
|
||||
<!-- KI-Assistent mit eingebettetem Chat -->
|
||||
<div class="glass-morphism p-6 sm:p-8 rounded-3xl transition-all duration-500 hover:-translate-y-1 hover:shadow-xl backdrop-blur-md border border-white/10">
|
||||
<h3 class="text-xl md:text-2xl font-bold mb-4 flex flex-wrap sm:flex-nowrap items-center text-gray-800 dark:text-white">
|
||||
<div class="w-10 h-10 sm:w-12 sm:h-12 rounded-2xl bg-gradient-to-r from-purple-600 to-blue-600 flex items-center justify-center mr-3 sm:mr-4 shadow-lg transform transition-transform duration-300 hover:scale-110">
|
||||
<i class="fa-solid fa-robot text-white text-base sm:text-lg"></i>
|
||||
</div>
|
||||
<span class="mt-1 sm:mt-0">KI-Assistent</span>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-5 sm:mb-6 text-sm md:text-base leading-relaxed">
|
||||
Stelle Fragen, lasse dir Themen erklären oder finde neue Verbindungen mit Hilfe
|
||||
unseres KI-Assistenten.
|
||||
</p>
|
||||
|
||||
<!-- Verbesserte Suchleiste -->
|
||||
<div class="mb-5 sm:mb-6">
|
||||
<div class="relative group">
|
||||
<div class="absolute inset-0 bg-gradient-to-r from-purple-500/20 to-blue-500/20 rounded-xl blur-sm group-hover:blur-md transition-all duration-300 opacity-70 group-hover:opacity-100"></div>
|
||||
<input type="text" placeholder="Frage den KI-Assistenten"
|
||||
class="relative w-full px-4 sm:px-5 py-3 sm:py-4 rounded-xl border bg-white/70 dark:bg-gray-800/70 border-gray-300 dark:border-gray-700 shadow-sm focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200 placeholder-gray-400 dark:placeholder-gray-500 text-gray-700 dark:text-gray-200"
|
||||
onkeypress="if(event.keyCode==13) window.MindMap.assistant.toggleAssistant(true);">
|
||||
<button onclick="window.MindMap.assistant.toggleAssistant(true)"
|
||||
class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 dark:text-gray-400 hover:text-purple-500 dark:hover:text-purple-400 focus:outline-none transition-all duration-200 w-8 h-8 sm:w-10 sm:h-10 flex items-center justify-center bg-white/50 dark:bg-gray-700/50 rounded-full hover:bg-purple-100 dark:hover:bg-purple-900/30">
|
||||
<i class="fa-solid fa-search text-sm sm:text-base"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="glass-morphism p-4 sm:p-5 rounded-2xl mb-5 sm:mb-6 transition-all duration-300 hover:shadow-md bg-gradient-to-br from-purple-500/5 to-blue-500/5 border border-white/10">
|
||||
<div class="flex items-start">
|
||||
<div class="w-8 h-8 sm:w-10 sm:h-10 rounded-xl bg-gradient-to-r from-purple-500 to-blue-500 flex items-center justify-center flex-shrink-0 mr-3 shadow-md">
|
||||
<i class="fa-solid fa-robot text-white text-xs sm:text-sm"></i>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-xs sm:text-sm text-gray-700 dark:text-gray-300">Frage den KI-Assistenten</p>
|
||||
<div class="mt-3 sm:mt-4 flex flex-wrap gap-2">
|
||||
<a href="{{ url_for('mindmap') }}" class="px-2 sm:px-3 py-1 sm:py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-lg sm:rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
Erkunde die Mindmap
|
||||
</a>
|
||||
<a href="{{ url_for('search_thoughts_page') }}" class="px-2 sm:px-3 py-1 sm:py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-lg sm:rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
Themen durchsuchen
|
||||
</a>
|
||||
<a href="#" class="px-2 sm:px-3 py-1 sm:py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-lg sm:rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
Beziehungen erforschen
|
||||
</a>
|
||||
<!-- Eingebettetes Chat-Interface -->
|
||||
<div id="embedded-assistant" class="rounded-xl border border-gray-200/50 dark:border-gray-700/50 overflow-hidden flex flex-col h-[300px]">
|
||||
<!-- Chat Verlauf -->
|
||||
<div id="embedded-chat-messages" class="flex-grow p-4 overflow-y-auto space-y-3 bg-white/70 dark:bg-gray-800/70">
|
||||
<!-- Begrüßungsnachricht -->
|
||||
<div class="flex items-start space-x-2">
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-600 to-blue-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-robot text-white text-xs"></i>
|
||||
</div>
|
||||
<div class="max-w-[85%] bg-purple-100 dark:bg-gray-700 p-3 rounded-xl rounded-tl-none shadow-sm">
|
||||
<p class="text-sm text-gray-700 dark:text-gray-200">Hallo! Ich bin dein KI-Assistent. Wie kann ich dir helfen?</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chat Eingabe -->
|
||||
<div class="p-3 border-t border-gray-200/70 dark:border-gray-700/70 bg-gray-50/90 dark:bg-gray-800/90">
|
||||
<form id="embedded-chat-form" class="flex items-center space-x-2">
|
||||
<input type="text" id="embedded-chat-input"
|
||||
placeholder="Stelle eine Frage..."
|
||||
class="flex-grow px-4 py-2 rounded-xl border bg-white/90 dark:bg-gray-700/90 border-gray-300 dark:border-gray-600 shadow-sm focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all duration-200 placeholder-gray-400 dark:placeholder-gray-500 text-gray-700 dark:text-gray-200">
|
||||
<button type="submit"
|
||||
class="p-2 rounded-xl bg-gradient-to-r from-purple-600 to-blue-600 text-white shadow-md hover:shadow-lg transition-all duration-200 hover:-translate-y-0.5">
|
||||
<i class="fa-solid fa-paper-plane"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<button onclick="window.MindMap.assistant.toggleAssistant(true)" class="btn-primary w-full text-center rounded-xl py-3 sm:py-3.5 shadow-md hover:shadow-lg transition-all duration-300 hover:-translate-y-1 flex items-center justify-center">
|
||||
<i class="fa-solid fa-comments mr-2"></i>
|
||||
<span>KI-Chat starten</span>
|
||||
|
||||
<!-- Schnelllinks unter dem Chat -->
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<button class="quick-query-btn px-2 sm:px-3 py-1 sm:py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-lg sm:rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
Was ist Systades?
|
||||
</button>
|
||||
<button class="quick-query-btn px-2 sm:px-3 py-1 sm:py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-lg sm:rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
Wie erstelle ich eine Mindmap?
|
||||
</button>
|
||||
<button class="quick-query-btn px-2 sm:px-3 py-1 sm:py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-lg sm:rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
Zeige neueste Gedanken
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Vollständigen KI-Chat öffnen -->
|
||||
<button onclick="window.MindMap.assistant.toggleAssistant(true)" class="mt-4 btn-primary w-full text-center rounded-xl py-2 sm:py-2.5 shadow-md hover:shadow-lg transition-all duration-300 hover:-translate-y-1 flex items-center justify-center">
|
||||
<i class="fa-solid fa-expand mr-2"></i>
|
||||
<span>Chat in Vollansicht öffnen</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
<!-- JavaScript für eingebetteten Chat -->
|
||||
{% block scripts %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Warten bis MindMap und der Assistent initialisiert sind
|
||||
const waitForAssistant = setInterval(() => {
|
||||
if (window.MindMap && window.MindMap.assistant) {
|
||||
clearInterval(waitForAssistant);
|
||||
initEmbeddedChat();
|
||||
}
|
||||
}, 200);
|
||||
|
||||
function initEmbeddedChat() {
|
||||
const chatForm = document.getElementById('embedded-chat-form');
|
||||
const chatInput = document.getElementById('embedded-chat-input');
|
||||
const messagesContainer = document.getElementById('embedded-chat-messages');
|
||||
const quickQueryBtns = document.querySelectorAll('.quick-query-btn');
|
||||
|
||||
// Event-Listener für das Chat-Formular
|
||||
chatForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const userMessage = chatInput.value.trim();
|
||||
if (!userMessage) return;
|
||||
|
||||
// Nachricht des Benutzers anzeigen
|
||||
appendMessage('user', userMessage);
|
||||
chatInput.value = '';
|
||||
|
||||
// Anzeigen, dass der Assistent antwortet
|
||||
const typingIndicator = appendTypingIndicator();
|
||||
|
||||
// API-Anfrage an den Assistenten senden
|
||||
sendToAssistant(userMessage)
|
||||
.then(response => {
|
||||
// Entferne Tipp-Indikator
|
||||
typingIndicator.remove();
|
||||
// Zeige Antwort des Assistenten an
|
||||
appendMessage('assistant', response);
|
||||
})
|
||||
.catch(error => {
|
||||
typingIndicator.remove();
|
||||
appendMessage('assistant', 'Es tut mir leid, ich konnte deine Nachricht nicht verarbeiten. Bitte versuche es später noch einmal.');
|
||||
console.error('Fehler bei der Kommunikation mit dem Assistenten:', error);
|
||||
});
|
||||
});
|
||||
|
||||
// Schnellabfragen-Buttons
|
||||
quickQueryBtns.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const query = this.textContent.trim();
|
||||
chatInput.value = query;
|
||||
chatForm.dispatchEvent(new Event('submit'));
|
||||
});
|
||||
});
|
||||
|
||||
// Funktion zum Hinzufügen einer Nachricht zum Chat
|
||||
function appendMessage(sender, message) {
|
||||
const messageElement = document.createElement('div');
|
||||
messageElement.className = 'flex items-start space-x-2';
|
||||
|
||||
if (sender === 'user') {
|
||||
messageElement.innerHTML = `
|
||||
<div class="flex-grow"></div>
|
||||
<div class="max-w-[85%] bg-blue-100 dark:bg-blue-900/40 p-3 rounded-xl rounded-tr-none shadow-sm">
|
||||
<p class="text-sm text-gray-700 dark:text-gray-200">${message}</p>
|
||||
</div>
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-blue-500 to-indigo-500 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-user text-white text-xs"></i>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
messageElement.innerHTML = `
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-600 to-blue-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-robot text-white text-xs"></i>
|
||||
</div>
|
||||
<div class="max-w-[85%] bg-purple-100 dark:bg-gray-700 p-3 rounded-xl rounded-tl-none shadow-sm">
|
||||
<p class="text-sm text-gray-700 dark:text-gray-200">${message}</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
messagesContainer.appendChild(messageElement);
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
}
|
||||
|
||||
// Tipp-Indikator für "Assistent schreibt..."
|
||||
function appendTypingIndicator() {
|
||||
const indicatorElement = document.createElement('div');
|
||||
indicatorElement.className = 'flex items-start space-x-2 typing-indicator';
|
||||
indicatorElement.innerHTML = `
|
||||
<div class="w-8 h-8 rounded-full bg-gradient-to-r from-purple-600 to-blue-600 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fa-solid fa-robot text-white text-xs"></i>
|
||||
</div>
|
||||
<div class="max-w-[85%] bg-purple-100 dark:bg-gray-700 p-3 rounded-xl rounded-tl-none shadow-sm">
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 flex items-center">
|
||||
<span class="mr-1">Tipp</span>
|
||||
<span class="typing-dots flex space-x-1">
|
||||
<span class="w-1.5 h-1.5 bg-gray-500 dark:bg-gray-400 rounded-full animate-bounce" style="animation-delay: 0ms;"></span>
|
||||
<span class="w-1.5 h-1.5 bg-gray-500 dark:bg-gray-400 rounded-full animate-bounce" style="animation-delay: 150ms;"></span>
|
||||
<span class="w-1.5 h-1.5 bg-gray-500 dark:bg-gray-400 rounded-full animate-bounce" style="animation-delay: 300ms;"></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
messagesContainer.appendChild(indicatorElement);
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
return indicatorElement;
|
||||
}
|
||||
|
||||
// Sende Nachricht an den Assistenten und erhalte Antwort
|
||||
async function sendToAssistant(message) {
|
||||
try {
|
||||
const response = await fetch('/api/assistant', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
messages: [
|
||||
{ role: "system", content: "Du bist ein hilfreicher Assistent für das Wissensnetzwerk Systades." },
|
||||
{ role: "user", content: message }
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error || 'Unbekannter Fehler');
|
||||
}
|
||||
|
||||
return data.response || data.answer || 'Ich habe keine Antwort erhalten.';
|
||||
} catch (error) {
|
||||
console.error('Fehler bei der API-Anfrage:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user