Add flash message API and enhance mindmap visualization: Implement a new API endpoint for retrieving flash messages, integrate flash message display in the mindmap visualization, and improve user feedback with dynamic notifications. Update UI elements for better responsiveness and visual appeal, while removing obsolete background image references.
This commit is contained in:
Binary file not shown.
@@ -207,6 +207,26 @@ def settings():
|
||||
|
||||
return render_template('settings.html')
|
||||
|
||||
# API-Endpunkt für Flash-Nachrichten
|
||||
@app.route('/api/get_flash_messages')
|
||||
def get_flash_messages():
|
||||
"""Liefert aktuelle Flash-Nachrichten für API/JS-Clients."""
|
||||
# Hole alle gespeicherten Flash-Nachrichten
|
||||
messages = []
|
||||
flashed_messages = session.get('_flashes', [])
|
||||
|
||||
# Formatierung der Nachrichten für die API-Antwort
|
||||
for category, message in flashed_messages:
|
||||
messages.append({
|
||||
'category': category,
|
||||
'message': message
|
||||
})
|
||||
|
||||
# Lösche die Nachrichten aus der Session, nachdem sie abgerufen wurden
|
||||
session.pop('_flashes', None)
|
||||
|
||||
return jsonify(messages)
|
||||
|
||||
# Routes für rechtliche Seiten
|
||||
@app.route('/impressum/')
|
||||
def impressum():
|
||||
@@ -1099,6 +1119,13 @@ def my_account():
|
||||
|
||||
return render_template('my_account.html', bookmarked_thoughts=bookmarked_thoughts)
|
||||
|
||||
# Dummy-Route, um 404-Fehler für fehlende Netzwerk-Hintergrundbilder zu vermeiden
|
||||
@app.route('/static/network-bg.jpg')
|
||||
@app.route('/static/network-bg.svg')
|
||||
def dummy_network_bg():
|
||||
"""Leere Antwort für die nicht mehr verwendeten Netzwerk-Hintergrundbilder."""
|
||||
return '', 200
|
||||
|
||||
# Flask starten
|
||||
if __name__ == '__main__':
|
||||
with app.app_context():
|
||||
|
||||
@@ -32,6 +32,9 @@ class MindMapVisualization {
|
||||
this.tooltipDiv = null;
|
||||
this.isLoading = true;
|
||||
|
||||
// Flash-Nachrichten-Container
|
||||
this.flashContainer = null;
|
||||
|
||||
// Erweiterte Farbpalette für Knotentypen
|
||||
this.colorPalette = {
|
||||
'default': '#b38fff',
|
||||
@@ -57,6 +60,7 @@ class MindMapVisualization {
|
||||
if (this.container.node()) {
|
||||
this.init();
|
||||
this.setupDefaultNodes();
|
||||
this.setupFlashMessages();
|
||||
|
||||
// Sofortige Datenladung
|
||||
window.setTimeout(() => {
|
||||
@@ -67,6 +71,183 @@ class MindMapVisualization {
|
||||
}
|
||||
}
|
||||
|
||||
// Flash-Nachrichten-System einrichten
|
||||
setupFlashMessages() {
|
||||
// Flash-Container erstellen, falls er noch nicht existiert
|
||||
if (!document.getElementById('mindmap-flash-container')) {
|
||||
this.flashContainer = document.createElement('div');
|
||||
this.flashContainer.id = 'mindmap-flash-container';
|
||||
this.flashContainer.className = 'mindmap-flash-container';
|
||||
this.flashContainer.style.position = 'fixed';
|
||||
this.flashContainer.style.top = '20px';
|
||||
this.flashContainer.style.right = '20px';
|
||||
this.flashContainer.style.zIndex = '1000';
|
||||
this.flashContainer.style.maxWidth = '350px';
|
||||
this.flashContainer.style.display = 'flex';
|
||||
this.flashContainer.style.flexDirection = 'column';
|
||||
this.flashContainer.style.gap = '10px';
|
||||
document.body.appendChild(this.flashContainer);
|
||||
} else {
|
||||
this.flashContainer = document.getElementById('mindmap-flash-container');
|
||||
}
|
||||
|
||||
// Prüfen, ob Server-seitige Flash-Nachrichten existieren und anzeigen
|
||||
this.checkForServerFlashMessages();
|
||||
}
|
||||
|
||||
// Prüft auf Server-seitige Flash-Nachrichten
|
||||
async checkForServerFlashMessages() {
|
||||
try {
|
||||
const response = await fetch('/api/get_flash_messages');
|
||||
if (response.ok) {
|
||||
const messages = await response.json();
|
||||
messages.forEach(message => {
|
||||
this.showFlash(message.message, message.category);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Fehler beim Abrufen der Flash-Nachrichten:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// Zeigt eine Flash-Nachricht an
|
||||
showFlash(message, type = 'info', duration = 5000) {
|
||||
if (!this.flashContainer) return;
|
||||
|
||||
const flashElement = document.createElement('div');
|
||||
flashElement.className = `mindmap-flash flash-${type}`;
|
||||
flashElement.style.padding = '12px 18px';
|
||||
flashElement.style.borderRadius = '8px';
|
||||
flashElement.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
|
||||
flashElement.style.display = 'flex';
|
||||
flashElement.style.alignItems = 'center';
|
||||
flashElement.style.justifyContent = 'space-between';
|
||||
flashElement.style.fontSize = '14px';
|
||||
flashElement.style.fontWeight = '500';
|
||||
flashElement.style.backdropFilter = 'blur(10px)';
|
||||
flashElement.style.opacity = '0';
|
||||
flashElement.style.transform = 'translateY(-20px)';
|
||||
flashElement.style.transition = 'all 0.3s ease';
|
||||
|
||||
// Spezifische Stile je nach Nachrichtentyp
|
||||
switch(type) {
|
||||
case 'success':
|
||||
flashElement.style.backgroundColor = 'rgba(34, 197, 94, 0.9)';
|
||||
flashElement.style.borderLeft = '5px solid #16a34a';
|
||||
flashElement.style.color = 'white';
|
||||
break;
|
||||
case 'error':
|
||||
flashElement.style.backgroundColor = 'rgba(239, 68, 68, 0.9)';
|
||||
flashElement.style.borderLeft = '5px solid #dc2626';
|
||||
flashElement.style.color = 'white';
|
||||
break;
|
||||
case 'warning':
|
||||
flashElement.style.backgroundColor = 'rgba(245, 158, 11, 0.9)';
|
||||
flashElement.style.borderLeft = '5px solid #d97706';
|
||||
flashElement.style.color = 'white';
|
||||
break;
|
||||
default: // info
|
||||
flashElement.style.backgroundColor = 'rgba(59, 130, 246, 0.9)';
|
||||
flashElement.style.borderLeft = '5px solid #2563eb';
|
||||
flashElement.style.color = 'white';
|
||||
}
|
||||
|
||||
// Icon je nach Nachrichtentyp
|
||||
let icon = '';
|
||||
switch(type) {
|
||||
case 'success':
|
||||
icon = '<i class="fas fa-check-circle"></i>';
|
||||
break;
|
||||
case 'error':
|
||||
icon = '<i class="fas fa-exclamation-circle"></i>';
|
||||
break;
|
||||
case 'warning':
|
||||
icon = '<i class="fas fa-exclamation-triangle"></i>';
|
||||
break;
|
||||
default:
|
||||
icon = '<i class="fas fa-info-circle"></i>';
|
||||
}
|
||||
|
||||
// Inhalt der Nachricht mit Icon
|
||||
const contentWrapper = document.createElement('div');
|
||||
contentWrapper.style.display = 'flex';
|
||||
contentWrapper.style.alignItems = 'center';
|
||||
contentWrapper.style.gap = '12px';
|
||||
|
||||
const iconElement = document.createElement('div');
|
||||
iconElement.className = 'flash-icon';
|
||||
iconElement.innerHTML = icon;
|
||||
|
||||
const textElement = document.createElement('div');
|
||||
textElement.className = 'flash-text';
|
||||
textElement.textContent = message;
|
||||
|
||||
contentWrapper.appendChild(iconElement);
|
||||
contentWrapper.appendChild(textElement);
|
||||
|
||||
// Schließen-Button
|
||||
const closeButton = document.createElement('button');
|
||||
closeButton.className = 'flash-close';
|
||||
closeButton.innerHTML = '<i class="fas fa-times"></i>';
|
||||
closeButton.style.background = 'none';
|
||||
closeButton.style.border = 'none';
|
||||
closeButton.style.color = 'currentColor';
|
||||
closeButton.style.cursor = 'pointer';
|
||||
closeButton.style.marginLeft = '15px';
|
||||
closeButton.style.padding = '3px';
|
||||
closeButton.style.fontSize = '14px';
|
||||
closeButton.style.opacity = '0.7';
|
||||
closeButton.style.transition = 'opacity 0.2s';
|
||||
|
||||
closeButton.addEventListener('mouseover', () => {
|
||||
closeButton.style.opacity = '1';
|
||||
});
|
||||
|
||||
closeButton.addEventListener('mouseout', () => {
|
||||
closeButton.style.opacity = '0.7';
|
||||
});
|
||||
|
||||
closeButton.addEventListener('click', () => {
|
||||
this.removeFlash(flashElement);
|
||||
});
|
||||
|
||||
// Zusammenfügen
|
||||
flashElement.appendChild(contentWrapper);
|
||||
flashElement.appendChild(closeButton);
|
||||
|
||||
// Zum Container hinzufügen
|
||||
this.flashContainer.appendChild(flashElement);
|
||||
|
||||
// Animation einblenden
|
||||
setTimeout(() => {
|
||||
flashElement.style.opacity = '1';
|
||||
flashElement.style.transform = 'translateY(0)';
|
||||
}, 10);
|
||||
|
||||
// Automatisches Ausblenden nach der angegebenen Zeit
|
||||
if (duration > 0) {
|
||||
setTimeout(() => {
|
||||
this.removeFlash(flashElement);
|
||||
}, duration);
|
||||
}
|
||||
|
||||
return flashElement;
|
||||
}
|
||||
|
||||
// Entfernt eine Flash-Nachricht mit Animation
|
||||
removeFlash(flashElement) {
|
||||
if (!flashElement) return;
|
||||
|
||||
flashElement.style.opacity = '0';
|
||||
flashElement.style.transform = 'translateY(-20px)';
|
||||
|
||||
setTimeout(() => {
|
||||
if (flashElement.parentNode) {
|
||||
flashElement.parentNode.removeChild(flashElement);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// Standardknoten als Fallback einrichten, falls die API nicht reagiert
|
||||
setupDefaultNodes() {
|
||||
// Basis-Mindmap mit Hauptthemen
|
||||
@@ -301,6 +482,9 @@ class MindMapVisualization {
|
||||
|
||||
// Lade-Animation ausblenden
|
||||
this.hideLoading();
|
||||
|
||||
// Erfolgreiche Ladung melden
|
||||
this.showFlash('Mindmap-Daten erfolgreich geladen', 'success');
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Mindmap-Daten:', error);
|
||||
|
||||
@@ -310,6 +494,7 @@ class MindMapVisualization {
|
||||
|
||||
// Fehler anzeigen
|
||||
this.showError('Mindmap-Daten konnten nicht geladen werden. Verwende Standarddaten.');
|
||||
this.showFlash('Fehler beim Laden der Mindmap-Daten. Standarddaten werden angezeigt.', 'error');
|
||||
|
||||
// Visualisierung auch im Fehlerfall aktualisieren
|
||||
this.updateVisualization();
|
||||
@@ -992,6 +1177,9 @@ class MindMapVisualization {
|
||||
window.onNodeDeselected();
|
||||
}
|
||||
|
||||
// Flash-Nachricht für abgewählten Knoten
|
||||
this.showFlash('Knotenauswahl aufgehoben', 'info', 2000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1083,6 +1271,7 @@ class MindMapVisualization {
|
||||
|
||||
if (!thoughtContainer || !thoughtsList) {
|
||||
console.error('Gedanken-Container nicht gefunden');
|
||||
this.showFlash('Fehler: Gedanken-Container nicht gefunden', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1118,6 +1307,9 @@ class MindMapVisualization {
|
||||
thoughtsList.innerHTML = '';
|
||||
}
|
||||
|
||||
// Flash-Nachricht über ausgewählten Knoten
|
||||
this.showFlash(`Knoten "${node.name}" ausgewählt`, 'info');
|
||||
|
||||
// Verzögerung für Animation
|
||||
setTimeout(() => {
|
||||
// API-Aufruf für echte Daten aus der Datenbank
|
||||
@@ -1133,6 +1325,7 @@ class MindMapVisualization {
|
||||
this.renderThoughts(thoughts, thoughtsList);
|
||||
} else {
|
||||
this.renderEmptyThoughts(thoughtsList, node);
|
||||
this.showFlash(`Keine Gedanken zu "${node.name}" gefunden`, 'warning');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -1141,6 +1334,7 @@ class MindMapVisualization {
|
||||
loadingIndicator.style.display = 'none';
|
||||
}
|
||||
this.renderErrorState(thoughtsList);
|
||||
this.showFlash('Fehler beim Laden der Gedanken. Bitte versuche es später erneut.', 'error');
|
||||
});
|
||||
}, 600); // Verzögerung für bessere UX
|
||||
}
|
||||
@@ -1152,6 +1346,7 @@ class MindMapVisualization {
|
||||
const id = nodeId.toString().split('_')[1];
|
||||
if (!id) {
|
||||
console.warn('Ungültige Node-ID: ', nodeId);
|
||||
this.showFlash('Ungültige Knoten-ID: ' + nodeId, 'warning');
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -1164,9 +1359,17 @@ class MindMapVisualization {
|
||||
|
||||
const thoughts = await response.json();
|
||||
console.log('Geladene Gedanken für Knoten:', thoughts);
|
||||
|
||||
if (thoughts.length > 0) {
|
||||
this.showFlash(`${thoughts.length} Gedanken zum Thema geladen`, 'info');
|
||||
} else {
|
||||
this.showFlash('Keine Gedanken für diesen Knoten gefunden', 'info');
|
||||
}
|
||||
|
||||
return thoughts;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Gedanken für Knoten:', error);
|
||||
this.showFlash('Fehler beim Laden der Gedanken', 'error');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -1282,10 +1485,16 @@ class MindMapVisualization {
|
||||
d3.zoom().transform,
|
||||
d3.zoomIdentity.translate(x, y).scale(scale)
|
||||
);
|
||||
|
||||
// Flash-Nachricht für Zentrierung
|
||||
if (node && node.name) {
|
||||
this.showFlash(`Ansicht auf "${node.name}" zentriert`, 'info', 2000);
|
||||
}
|
||||
}
|
||||
|
||||
// Fehlermeldung anzeigen
|
||||
showError(message) {
|
||||
// Standard-Fehlermeldung als Banner
|
||||
const errorBanner = d3.select('body').selectAll('.error-banner').data([0]);
|
||||
|
||||
const errorEnter = errorBanner.enter()
|
||||
@@ -1314,12 +1523,18 @@ class MindMapVisualization {
|
||||
.delay(5000)
|
||||
.duration(500)
|
||||
.style('bottom', '-100px');
|
||||
|
||||
// Auch als Flash-Nachricht anzeigen
|
||||
this.showFlash(message, 'error');
|
||||
}
|
||||
|
||||
// Fokussieren auf einen bestimmten Knoten per ID
|
||||
focusNode(nodeId) {
|
||||
const targetNode = this.nodes.find(n => n.id === nodeId);
|
||||
if (!targetNode) return;
|
||||
if (!targetNode) {
|
||||
this.showFlash(`Knoten mit ID "${nodeId}" nicht gefunden`, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ausgewählten Zustand zurücksetzen
|
||||
this.selectedNode = null;
|
||||
@@ -1339,6 +1554,8 @@ class MindMapVisualization {
|
||||
d3.zoom().transform,
|
||||
transform
|
||||
);
|
||||
|
||||
this.showFlash(`Fokus auf Knoten "${targetNode.name}" gesetzt`, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1358,6 +1575,8 @@ class MindMapVisualization {
|
||||
.style('display', 'block')
|
||||
.style('stroke-opacity', 0.5);
|
||||
|
||||
this.showFlash('Suchfilter zurückgesetzt', 'info', 2000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1393,6 +1612,9 @@ class MindMapVisualization {
|
||||
// Wenn mehr als ein Knoten gefunden wurde, Simulation mit reduzierter Stärke neu starten
|
||||
if (matchingNodes.length > 1) {
|
||||
this.simulation.alpha(0.3).restart();
|
||||
this.showFlash(`${matchingNodes.length} Knoten für "${searchTerm}" gefunden`, 'success');
|
||||
} else if (matchingNodes.length === 0) {
|
||||
this.showFlash(`Keine Knoten für "${searchTerm}" gefunden`, 'warning');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('/static/network-bg.jpg');
|
||||
background: rgba(179, 143, 255, 0.05);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
opacity: 0.15;
|
||||
|
||||
@@ -42,34 +42,10 @@ function initNetworkBackground() {
|
||||
networkImage = new Image();
|
||||
networkImage.crossOrigin = "anonymous"; // Vermeidet CORS-Probleme
|
||||
|
||||
// Event-Handler für Fehler - Fallback auf Standard-Hintergrund
|
||||
networkImage.onerror = function() {
|
||||
loadAttempts++;
|
||||
if (loadAttempts < MAX_LOAD_ATTEMPTS) {
|
||||
// Wenn SVG fehlschlägt, versuche JPG
|
||||
if (networkImage.src.endsWith('svg')) {
|
||||
networkImage.src = '/static/network-bg.jpg';
|
||||
} else {
|
||||
// Wenn beide fehlschlagen, starte einfach Animation ohne Hintergrund
|
||||
console.log("Konnte kein Hintergrundbild laden, verwende einfachen Hintergrund");
|
||||
isImageLoaded = true; // Trotzdem Animation starten
|
||||
startAnimation();
|
||||
}
|
||||
} else {
|
||||
// Zu viele Versuche, verwende einfachen Hintergrund
|
||||
console.log("Konnte kein Hintergrundbild laden, verwende einfachen Hintergrund");
|
||||
isImageLoaded = true; // Trotzdem Animation starten
|
||||
startAnimation();
|
||||
}
|
||||
};
|
||||
|
||||
// Versuche zuerst die SVG-Version zu laden
|
||||
networkImage.src = '/static/network-bg.svg';
|
||||
|
||||
networkImage.onload = function() {
|
||||
isImageLoaded = true;
|
||||
startAnimation();
|
||||
};
|
||||
// Keine Bilder laden, direkt Fallback-Hintergrund verwenden
|
||||
console.log("Verwende einfachen Hintergrund ohne Bilddateien");
|
||||
isImageLoaded = true; // Animation ohne Hintergrundbild starten
|
||||
startAnimation();
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener('resize', debounce(resizeCanvas, 250));
|
||||
|
||||
@@ -540,7 +540,7 @@
|
||||
<!-- Globaler Hintergrund -->
|
||||
<div class="full-page-bg"></div>
|
||||
<!-- Statischer Fallback-Hintergrund (wird nur angezeigt, wenn JavaScript deaktiviert ist) -->
|
||||
<div class="fixed inset-0 z-[-9] bg-cover bg-center opacity-50" style="background-image: url('{{ url_for('static', filename='network-bg.jpg') }}');"></div>
|
||||
<div class="fixed inset-0 z-[-9] bg-cover bg-center opacity-50"></div>
|
||||
|
||||
<!-- App-Container -->
|
||||
<div id="app-container" class="flex flex-col min-h-screen" x-data="layout">
|
||||
|
||||
@@ -100,17 +100,23 @@
|
||||
in einem interaktiven Wissensnetzwerk.
|
||||
</p>
|
||||
<div class="flex flex-col sm:flex-row gap-5 justify-center">
|
||||
<a href="{{ url_for('mindmap') }}" class="btn-primary text-lg px-8 py-4 rounded-2xl shadow-lg hover:shadow-xl hover:shadow-purple-500/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fa-solid fa-diagram-project mr-3 animate-pulse"></i>
|
||||
Mindmap erkunden
|
||||
<a href="{{ url_for('mindmap') }}" class="group transition-all duration-300 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white font-medium text-lg px-8 py-4 rounded-2xl shadow-lg hover:shadow-xl hover:shadow-purple-500/20 transform hover:-translate-y-1">
|
||||
<span class="flex items-center justify-center">
|
||||
<i class="fa-solid fa-diagram-project mr-3 text-purple-200 group-hover:text-white transition-all duration-300 animate-pulse"></i>
|
||||
<span class="relative">
|
||||
Mindmap erkunden
|
||||
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-white group-hover:w-full transition-all duration-300"></span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
{% if not current_user.is_authenticated %}
|
||||
<a href="{{ url_for('register') }}" class="btn-secondary text-lg px-8 py-4 rounded-2xl shadow-lg hover:shadow-xl hover:shadow-blue-500/10">
|
||||
<span class="flex items-center">
|
||||
<i class="fa-solid fa-user-plus mr-3 icon-pulse"></i>
|
||||
Konto erstellen
|
||||
<a href="{{ url_for('register') }}" class="group transition-all duration-300 bg-gradient-to-r from-blue-500 to-cyan-500 hover:from-blue-600 hover:to-cyan-600 text-white font-medium text-lg px-8 py-4 rounded-2xl shadow-lg hover:shadow-xl hover:shadow-blue-500/20 transform hover:-translate-y-1">
|
||||
<span class="flex items-center justify-center">
|
||||
<i class="fa-solid fa-user-plus mr-3 text-blue-200 group-hover:text-white transition-all duration-300 icon-pulse"></i>
|
||||
<span class="relative">
|
||||
Konto erstellen
|
||||
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-white group-hover:w-full transition-all duration-300"></span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
@@ -267,21 +273,23 @@
|
||||
</section>
|
||||
|
||||
<!-- Call to Action Section -->
|
||||
<section class="py-20 relative overflow-hidden">
|
||||
<section class="py-16 sm:py-20 md:py-24 relative overflow-hidden">
|
||||
<div class="max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<div class="glass-effect p-8 md:p-12 rounded-3xl transform transition-all duration-500 hover:-translate-y-2 hover:shadow-xl bg-gradient-to-br from-purple-500/10 to-blue-500/10 backdrop-blur-xl border border-white/10">
|
||||
<div class="md:flex md:items-center md:justify-between">
|
||||
<div class="glass-effect p-6 sm:p-8 md:p-12 rounded-3xl transform transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl bg-gradient-to-br from-purple-500/15 to-blue-500/15 backdrop-blur-xl border border-white/10 shadow-lg">
|
||||
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-6">
|
||||
<div class="md:w-2/3">
|
||||
<h2 class="text-3xl font-bold mb-4 text-gray-900 dark:text-white">Bereit, <span class="gradient-text">Wissen</span> neu zu entdecken?</h2>
|
||||
<p class="text-gray-700 dark:text-gray-300 text-lg mb-6 md:mb-0">
|
||||
<h2 class="text-2xl sm:text-3xl lg:text-4xl font-bold mb-3 text-gray-900 dark:text-white leading-tight">
|
||||
Bereit, <span class="gradient-text bg-clip-text text-transparent bg-gradient-to-r from-purple-500 to-blue-500">Wissen</span> neu zu entdecken?
|
||||
</h2>
|
||||
<p class="text-gray-700 dark:text-gray-300 text-base sm:text-lg mb-6 md:mb-0 max-w-2xl">
|
||||
Starte jetzt deine Reise durch das Wissensnetzwerk und erschließe neue Perspektiven.
|
||||
</p>
|
||||
</div>
|
||||
<div class="md:w-1/3 text-center md:text-right">
|
||||
<a href="{{ url_for('mindmap') }}" class="inline-block btn-primary font-bold py-3.5 px-8 rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 hover:scale-105">
|
||||
<a href="{{ url_for('mindmap') }}" class="inline-flex items-center justify-center w-full md:w-auto btn-primary font-bold py-3 sm:py-3.5 px-6 sm:px-8 rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 transform hover:-translate-y-1 hover:scale-105 bg-gradient-to-r from-purple-600 to-blue-600 text-white">
|
||||
<span class="flex items-center justify-center">
|
||||
<i class="fa-solid fa-arrow-right mr-2"></i>
|
||||
Zur Mindmap
|
||||
<span>Zur Mindmap</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -291,94 +299,101 @@
|
||||
</section>
|
||||
|
||||
<!-- Quick Access Section -->
|
||||
<section class="py-16">
|
||||
<section class="py-16 sm:py-20">
|
||||
<div class="max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 lg:gap-8">
|
||||
<!-- Themen-Übersicht -->
|
||||
<div class="glass-morphism p-8 rounded-3xl transition-all duration-500 hover:-translate-y-3 hover:shadow-xl">
|
||||
<div class="glass-morphism p-6 sm:p-8 rounded-3xl transition-all duration-500 hover:-translate-y-3 hover:shadow-xl border border-white/10 backdrop-blur-md">
|
||||
<h3 class="text-xl font-bold mb-4 flex items-center text-gray-800 dark:text-white">
|
||||
<div class="w-12 h-12 rounded-2xl bg-gradient-to-r from-violet-500 to-fuchsia-500 flex items-center justify-center mr-4 shadow-md">
|
||||
<i class="fa-solid fa-fire text-white text-lg"></i>
|
||||
<div class="w-10 h-10 sm:w-12 sm:h-12 rounded-2xl bg-gradient-to-r from-violet-500 to-fuchsia-500 flex items-center justify-center mr-3 sm:mr-4 shadow-md transform transition-transform duration-300 hover:scale-110">
|
||||
<i class="fa-solid fa-fire text-white text-base sm:text-lg"></i>
|
||||
</div>
|
||||
Themen-Übersicht
|
||||
<span class="text-lg sm:text-xl md:text-2xl">Themen-Übersicht</span>
|
||||
</h3>
|
||||
<div class="space-y-4 mb-6">
|
||||
<a href="{{ url_for('mindmap') }}" class="flex items-center p-3.5 rounded-xl hover:bg-gray-100/50 dark:hover:bg-white/5 transition-all duration-200 group">
|
||||
<div class="space-y-3 sm:space-y-4 mb-6">
|
||||
<a href="{{ url_for('mindmap') }}" class="flex items-center p-3 sm:p-3.5 rounded-xl hover:bg-gray-100/50 dark:hover:bg-white/5 transition-all duration-200 group">
|
||||
<div class="w-3 h-3 rounded-full bg-purple-400 mr-3 group-hover:scale-125 transition-transform"></div>
|
||||
<div class="flex-grow">
|
||||
<p class="font-medium text-gray-800 dark:text-gray-200">Wissensbereiche <span class="text-xs text-gray-500">(12)</span></p>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">Überblick über Themenbereiche</p>
|
||||
<p class="text-xs sm:text-sm text-gray-500 dark:text-gray-400">Überblick über Themenbereiche</p>
|
||||
</div>
|
||||
<i class="fa-solid fa-chevron-right text-gray-500 group-hover:translate-x-1 transition-transform"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('search_thoughts_page') }}" class="flex items-center p-3.5 rounded-xl hover:bg-gray-100/50 dark:hover:bg-white/5 transition-all duration-200 group">
|
||||
<a href="{{ url_for('search_thoughts_page') }}" class="flex items-center p-3 sm:p-3.5 rounded-xl hover:bg-gray-100/50 dark:hover:bg-white/5 transition-all duration-200 group">
|
||||
<div class="w-3 h-3 rounded-full bg-blue-400 mr-3 group-hover:scale-125 transition-transform"></div>
|
||||
<div class="flex-grow">
|
||||
<p class="font-medium text-gray-800 dark:text-gray-200">Gedanken <span class="text-xs text-gray-500">(87)</span></p>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">Konkrete Einträge durchsuchen</p>
|
||||
<p class="text-xs sm:text-sm text-gray-500 dark:text-gray-400">Konkrete Einträge durchsuchen</p>
|
||||
</div>
|
||||
<i class="fa-solid fa-chevron-right text-gray-500 group-hover:translate-x-1 transition-transform"></i>
|
||||
</a>
|
||||
<a href="#" class="flex items-center p-3.5 rounded-xl hover:bg-gray-100/50 dark:hover:bg-white/5 transition-all duration-200 group">
|
||||
<a href="#" class="flex items-center p-3 sm:p-3.5 rounded-xl hover:bg-gray-100/50 dark:hover:bg-white/5 transition-all duration-200 group">
|
||||
<div class="w-3 h-3 rounded-full bg-green-400 mr-3 group-hover:scale-125 transition-transform"></div>
|
||||
<div class="flex-grow">
|
||||
<p class="font-medium text-gray-800 dark:text-gray-200">Verbindungen <span class="text-xs text-gray-500">(34)</span></p>
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">Beziehungen zwischen Gedanken</p>
|
||||
<p class="text-xs sm:text-sm text-gray-500 dark:text-gray-400">Beziehungen zwischen Gedanken</p>
|
||||
</div>
|
||||
<i class="fa-solid fa-chevron-right text-gray-500 group-hover:translate-x-1 transition-transform"></i>
|
||||
</a>
|
||||
</div>
|
||||
<a href="{{ url_for('search_thoughts_page') }}" class="btn-primary w-full text-center rounded-xl py-3.5">Alle Themen entdecken</a>
|
||||
<a href="{{ url_for('search_thoughts_page') }}" class="btn-primary w-full text-center rounded-xl py-3 sm:py-3.5 transform transition-all duration-300 hover:-translate-y-1 hover:shadow-lg flex items-center justify-center">
|
||||
<span>Alle Themen entdecken</span>
|
||||
<i class="fa-solid fa-arrow-right ml-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Google-like KI-Assistent Search Bar -->
|
||||
<div class="glass-morphism p-8 rounded-3xl transition-all duration-500 hover:-translate-y-3 hover:shadow-xl">
|
||||
<h3 class="text-xl font-bold mb-4 flex items-center text-gray-800 dark:text-white">
|
||||
<div class="w-12 h-12 rounded-2xl bg-gradient-to-r from-purple-500 to-blue-500 flex items-center justify-center mr-4 shadow-md">
|
||||
<i class="fa-solid fa-robot text-white text-lg"></i>
|
||||
<!-- 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">
|
||||
<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>
|
||||
KI-Assistent
|
||||
<span class="mt-1 sm:mt-0">KI-Assistent</span>
|
||||
</h3>
|
||||
<p class="text-gray-600 dark:text-gray-300 mb-6">
|
||||
<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>
|
||||
|
||||
<!-- Google-like Search Bar -->
|
||||
<div class="mb-6">
|
||||
<div class="relative">
|
||||
<!-- 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="w-full px-4 py-3.5 rounded-xl border bg-white/50 dark:bg-gray-800/50 border-gray-300 dark:border-gray-700 shadow-sm focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-all duration-200"
|
||||
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-2 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">
|
||||
<i class="fa-solid fa-search"></i>
|
||||
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-5 rounded-2xl 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="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-10 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"></i>
|
||||
<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-sm text-gray-700 dark:text-gray-300">Frage den KI-Assistenten</p>
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<a href="{{ url_for('mindmap') }}" class="px-3 py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
<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-3 py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
<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-3 py-1.5 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800/70 dark:hover:bg-gray-700/80 rounded-xl text-xs text-gray-700 dark:text-gray-300 transition-all duration-200 hover:-translate-y-0.5 shadow-sm hover:shadow">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button onclick="window.MindMap.assistant.toggleAssistant(true)" class="btn-primary w-full text-center rounded-xl py-3.5 shadow-md hover:shadow-lg transition-all duration-300 hover:-translate-y-1">KI-Chat starten</button>
|
||||
<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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -516,9 +516,7 @@
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('/static/network-bg.svg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-image: none;
|
||||
opacity: 0.2;
|
||||
z-index: -1;
|
||||
animation: pulse 10s ease-in-out infinite alternate;
|
||||
|
||||
@@ -3,39 +3,39 @@
|
||||
{% block title %}Suche{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="flex flex-col md:flex-row gap-6">
|
||||
<!-- Filter-Sidebar -->
|
||||
<div class="col-lg-3 col-md-4 mb-4">
|
||||
<div class="glass">
|
||||
<h4 class="mb-4">Erweiterte Suche</h4>
|
||||
<div class="w-full md:w-1/3 lg:w-1/4 mb-6">
|
||||
<div class="bg-white/10 backdrop-blur-md rounded-xl p-6 shadow-lg">
|
||||
<h4 class="text-xl font-semibold mb-4">Erweiterte Suche</h4>
|
||||
<form id="search-form">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Suchbegriff</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium mb-1">Suchbegriff</label>
|
||||
<div class="flex items-center border rounded-lg overflow-hidden bg-white/5">
|
||||
<span class="px-3 py-2 text-gray-400">
|
||||
<i class="fas fa-search"></i>
|
||||
</span>
|
||||
<input type="text" class="form-control" name="q" placeholder="Suche...">
|
||||
<input type="text" class="w-full bg-transparent border-0 focus:ring-0 py-2 px-1" name="q" placeholder="Suche...">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Schlagworte</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium mb-1">Schlagworte</label>
|
||||
<div class="flex items-center border rounded-lg overflow-hidden bg-white/5">
|
||||
<span class="px-3 py-2 text-gray-400">
|
||||
<i class="fas fa-tags"></i>
|
||||
</span>
|
||||
<input type="text" class="form-control" name="keywords" placeholder="Schlagworte (kommagetrennt)">
|
||||
<input type="text" class="w-full bg-transparent border-0 focus:ring-0 py-2 px-1" name="keywords" placeholder="Schlagworte (kommagetrennt)">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Minimale Bewertung</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium mb-1">Minimale Bewertung</label>
|
||||
<div class="flex items-center border rounded-lg overflow-hidden bg-white/5">
|
||||
<span class="px-3 py-2 text-gray-400">
|
||||
<i class="fas fa-star"></i>
|
||||
</span>
|
||||
<select class="form-select" name="min_rating">
|
||||
<select class="w-full bg-transparent border-0 focus:ring-0 py-2 px-1" name="min_rating">
|
||||
<option value="">Alle</option>
|
||||
<option value="4">4+ Sterne</option>
|
||||
<option value="3">3+ Sterne</option>
|
||||
@@ -45,13 +45,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Quellentyp</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium mb-1">Quellentyp</label>
|
||||
<div class="flex items-center border rounded-lg overflow-hidden bg-white/5">
|
||||
<span class="px-3 py-2 text-gray-400">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
</span>
|
||||
<select class="form-select" name="source_type">
|
||||
<select class="w-full bg-transparent border-0 focus:ring-0 py-2 px-1" name="source_type">
|
||||
<option value="">Alle</option>
|
||||
<option value="PDF">PDF</option>
|
||||
<option value="Markdown">Markdown</option>
|
||||
@@ -60,13 +60,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label">Beziehungstyp</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<div class="mb-5">
|
||||
<label class="block text-sm font-medium mb-1">Beziehungstyp</label>
|
||||
<div class="flex items-center border rounded-lg overflow-hidden bg-white/5">
|
||||
<span class="px-3 py-2 text-gray-400">
|
||||
<i class="fas fa-project-diagram"></i>
|
||||
</span>
|
||||
<select class="form-select" name="relation_type">
|
||||
<select class="w-full bg-transparent border-0 focus:ring-0 py-2 px-1" name="relation_type">
|
||||
<option value="">Alle</option>
|
||||
<option value="SUPPORTS">Stützt</option>
|
||||
<option value="CONTRADICTS">Widerspricht</option>
|
||||
@@ -78,26 +78,26 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100">
|
||||
<i class="fas fa-search me-2"></i> Suchen
|
||||
<button type="submit" class="w-full bg-gradient-to-r from-blue-500 to-indigo-600 text-white py-2 px-4 rounded-lg hover:opacity-90 transition-all flex items-center justify-center">
|
||||
<i class="fas fa-search mr-2"></i> Suchen
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Suchergebnisse -->
|
||||
<div class="col-lg-9 col-md-8">
|
||||
<div class="glass mb-4">
|
||||
<h3 class="mb-3">Suchergebnisse</h3>
|
||||
<p class="opacity-75">Nutze die Filter links, um deine Suche zu präzisieren.</p>
|
||||
<div class="w-full md:w-2/3 lg:w-3/4">
|
||||
<div class="bg-white/10 backdrop-blur-md rounded-xl p-6 shadow-lg mb-6">
|
||||
<h3 class="text-2xl font-semibold mb-2">Suchergebnisse</h3>
|
||||
<p class="text-gray-300 text-sm">Nutze die Filter links, um deine Suche zu präzisieren.</p>
|
||||
</div>
|
||||
|
||||
<div id="search-results" class="mb-4">
|
||||
<div id="search-results" class="mb-6">
|
||||
<!-- Suchergebnisse werden hier dynamisch eingefügt -->
|
||||
<div class="glass text-center py-5">
|
||||
<i class="fas fa-search fa-3x mb-4" style="color: var(--primary-color);"></i>
|
||||
<h5 class="mb-3">Wissen entdecken</h5>
|
||||
<p class="opacity-75">Gib einen Suchbegriff ein, um in der wissenschaftlichen Wissensdatenbank zu suchen.</p>
|
||||
<div class="bg-white/10 backdrop-blur-md rounded-xl p-8 shadow-lg text-center">
|
||||
<i class="fas fa-search text-5xl mb-6 text-blue-400"></i>
|
||||
<h5 class="text-xl font-medium mb-3">Wissen entdecken</h5>
|
||||
<p class="text-gray-300">Gib einen Suchbegriff ein, um in der wissenschaftlichen Wissensdatenbank zu suchen.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user