diff --git a/static/js/update_mindmap.js b/static/js/update_mindmap.js index 57a1eb7..2c4476a 100644 --- a/static/js/update_mindmap.js +++ b/static/js/update_mindmap.js @@ -182,6 +182,322 @@ async function loadMindmapData(nodeId = null) { } } +// Funktion zum Initialisieren der Mindmap +async function initializeMindmap() { + try { + const data = await loadMindmapData(); + if (!data || !data.nodes || !data.edges) { + throw new Error('Ungültiges Datenformat: Mindmap-Daten fehlen oder sind unvollständig'); + } + + const elements = [ + // Knoten + ...data.nodes.map(node => ({ + data: { + id: node.id, + label: node.name, + category: node.category, + description: node.description, + hasChildren: node.has_children, + expanded: false, + color: node.color_code, + fontColor: '#ffffff', + fontSize: node.is_center ? 20 : 16 + } + })), + // Kanten + ...data.edges.map(edge => ({ + data: { + source: edge.source, + target: edge.target, + strength: edge.strength || 0.5 + } + })) + ]; + + // Bestehende Cytoscape-Instanz entfernen, falls vorhanden + if (window.cy && typeof window.cy.destroy === 'function') { + window.cy.destroy(); + } + + const cyContainer = document.getElementById('cy'); + if (!cyContainer) { + throw new Error('Mindmap-Container #cy nicht gefunden!'); + } + + window.cy = cytoscape({ + container: cyContainer, + elements: elements, + style: [ + { + selector: 'node', + style: mindmapStyles.node.base + }, + { + selector: 'node[isCenter]', + style: mindmapStyles.node.center + }, + { + selector: 'node:selected', + style: mindmapStyles.node.selected + }, + { + selector: 'edge', + style: mindmapStyles.edge.base + } + ], + layout: mindmapStyles.layout.base, + // Mausrad-Zooming deaktivieren + wheelSensitivity: 0, + minZoom: 0.2, + maxZoom: 2.5 + }); + + // Füge neuronale Eigenschaften zu allen Knoten hinzu + cy.nodes().forEach(node => { + const data = node.data(); + // Verwende mindmapConfig für Kategorie-Farben oder einen Standardwert + const categoryColor = data.category && mindmapConfig.categories[data.category] + ? mindmapConfig.categories[data.category].color + : '#60a5fa'; + + node.data({ + ...data, + neuronSize: data.neuronSize || 8, + neuronActivity: data.neuronActivity || 0.8, + refractionPeriod: Math.random() * 300 + 700, + threshold: Math.random() * 0.3 + 0.6, + lastFired: 0, + color: data.color || categoryColor + }); + }); + + // Füge synaptische Eigenschaften zu allen Kanten hinzu + cy.edges().forEach(edge => { + const data = edge.data(); + edge.data({ + ...data, + strength: data.strength || 0.5, + conductionVelocity: Math.random() * 0.5 + 0.3, + latency: Math.random() * 100 + 50 + }); + }); + + // Event-Listener für Knoten-Klicks + cy.on('tap', 'node', async function(evt) { + const node = evt.target; + console.log('Node clicked:', node.id(), 'hasChildren:', node.data('hasChildren'), 'expanded:', node.data('expanded')); + + if (node.data('hasChildren') && !node.data('expanded')) { + await loadSubthemes(node); + } + }); + + // Layout ausführen + cy.layout(mindmapStyles.layout.base).run(); + + // Starte neuronale Aktivitätssimulation + startNeuralActivitySimulation(cy); + + // Mindmap mit echten Daten befüllen (Styles, Farben etc.) + updateMindmap(); + + // Setze anfänglichen Zoom auf eine kleinere Stufe, damit mehr sichtbar ist + setTimeout(() => { + cy.zoom({ + level: 0.7, + renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 } + }); + cy.center(); + }, 300); + + return true; + } catch (error) { + console.error('Fehler bei der Mindmap-Initialisierung:', error); +/** + * Update Mindmap + * Dieses Skript fügt Knoten zur Mindmap hinzu und stellt sicher, + * dass sie im neuronalen Netzwerk-Design angezeigt werden. + * Implementiert Lazy Loading & Progressive Disclosure + */ + +// Neue zentrale Konfiguration +const mindmapConfig = { + categories: { + 'Philosophie': { + icon: 'fa-solid fa-lightbulb', + color: '#b71c1c', + description: 'Die Lehre vom Denken und der Erkenntnis' + }, + 'Wissenschaft': { + icon: 'fa-solid fa-atom', + color: '#f4b400', + description: 'Systematische Erforschung der Natur und Gesellschaft' + }, + 'Technologie': { + icon: 'fa-solid fa-microchip', + color: '#0d47a1', + description: 'Anwendung wissenschaftlicher Erkenntnisse' + }, + 'Künste': { + icon: 'fa-solid fa-palette', + color: '#c2185b', + description: 'Kreativer Ausdruck und künstlerische Gestaltung' + } + }, + defaultNodeStyle: { + fontSize: 18, + fontColor: '#fff', + neuronSize: 8, + neuronActivity: 0.8 + }, + centerNodeStyle: { + fontSize: 22, + fontColor: '#222', + neuronSize: 12, + neuronActivity: 1.0, + color: '#f5f5f5', + icon: 'fa-solid fa-circle' + } +}; + +// Zentrale Styling-Konfiguration +const mindmapStyles = { + node: { + base: { + 'background-color': 'data(color)', + 'label': 'data(label)', + 'color': '#ffffff', + 'text-background-color': 'rgba(0, 0, 0, 0.7)', + 'text-background-opacity': 0.8, + 'text-background-padding': '4px', + 'text-valign': 'center', + 'text-halign': 'center', + 'font-size': 16, + 'width': 40, + 'height': 40, + 'border-width': 2, + 'border-color': '#ffffff', + 'border-opacity': 0.8, + 'shape': 'ellipse', + 'background-opacity': 0.85 + }, + center: { + 'background-color': '#f5f5f5', + 'color': '#222', + 'font-size': 20, + 'border-width': 3, + 'width': 100, + 'height': 100 + }, + selected: { + 'border-color': '#f59e42', + 'border-width': 3, + 'background-opacity': 1 + } + }, + edge: { + base: { + 'width': function(ele) { + return ele.data('strength') ? ele.data('strength') * 2 : 1; + }, + 'line-color': function(ele) { + const sourceColor = ele.source().data('color'); + return sourceColor || '#8a8aaa'; + }, + 'line-opacity': function(ele) { + return ele.data('strength') ? ele.data('strength') * 0.6 : 0.4; + }, + 'curve-style': 'bezier', + 'target-arrow-shape': 'none', + 'control-point-distances': [30, -30], + 'control-point-weights': [0.5, 0.5] + } + }, + layout: { + base: { + name: 'cose', + animate: true, + animationDuration: 500, + refresh: 20, + fit: true, + padding: 30, + nodeRepulsion: 4500, + idealEdgeLength: 50, + edgeElasticity: 0.45, + randomize: true, + componentSpacing: 100, + nodeOverlap: 20, + gravity: 0.25, + initialTemp: 1000, + coolingFactor: 0.95, + minTemp: 1 + } + } +}; + +// Globale Variable für die Mindmap-Daten +let mindmapData = null; + +// Funktion zum Laden der Mindmap-Daten aus der Datenbank +async function loadMindmapData(nodeId = null) { + try { + const apiUrl = nodeId ? `/api/mindmap/${nodeId}` : '/api/mindmap/root'; + console.log('Lade Mindmap-Daten von:', apiUrl); + + const response = await fetch(apiUrl); + console.log('API-Antwort Status:', response.status); + + if (!response.ok) { + let errorData; + try { + errorData = await response.json(); + console.log('API-Fehler Details:', errorData); + } catch (e) { + console.error('Fehler beim Parsen der Fehlerantwort:', e); + errorData = { + error: `HTTP-Fehler ${response.status}: ${response.statusText}` + }; + } + + // Fehlerobjekt für die Benachrichtigung erstellen + const errorMessage = errorData.error || 'Unbekannter Fehler'; + + showUINotification(errorMessage, 'error'); + throw new Error(errorMessage); + } + + const data = await response.json(); + console.log('Geladene Mindmap-Daten:', data); + + if (!data.success) { + const errorMessage = data.error || 'Mindmap-Daten konnten nicht geladen werden'; + showUINotification(errorMessage, 'error'); + throw new Error(errorMessage); + } + + // Überprüfen, ob Nodes und Edges existieren + if (!data.nodes || !data.edges) { + const errorMessage = 'Ungültiges Datenformat: Nodes oder Edges fehlen'; + showUINotification(errorMessage, 'error'); + throw new Error(errorMessage); + } + + // Erfolgreiche Antwort + mindmapData = data; // Speichere die Daten in der globalen Variable + showUINotification('Mindmap-Daten erfolgreich geladen', 'success'); + return data; + } catch (error) { + console.error('Fehler beim Laden der Mindmap-Daten:', error); + + // Stelle sicher, dass wir eine aussagekräftige Fehlermeldung haben + const errorMessage = error.message || 'Unbekannter Fehler beim Laden der Mindmap-Daten'; + + showUINotification(errorMessage, 'error'); + throw error; + } +} + // Funktion zum Initialisieren der Mindmap async function initializeMindmap() { try { diff --git a/templates/mindmap.html b/templates/mindmap.html index 84cbf50..7919a8b 100644 --- a/templates/mindmap.html +++ b/templates/mindmap.html @@ -20,6 +20,46 @@ background: transparent; } + /* Zoom-Toolbar */ + .mindmap-toolbar { + position: absolute; + top: 80px; + left: 50%; + transform: translateX(-50%); + display: flex; + gap: 8px; + padding: 8px; + background: rgba(30, 41, 59, 0.8); + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); + z-index: 10; + backdrop-filter: blur(8px); + border: 1px solid rgba(255, 255, 255, 0.1); + } + + .mindmap-toolbar button { + width: 40px; + height: 40px; + border: none; + background: rgba(255, 255, 255, 0.1); + color: white; + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.2s ease; + } + + .mindmap-toolbar button:hover { + background: rgba(139, 92, 246, 0.5); + transform: translateY(-2px); + } + + .mindmap-toolbar button i { + font-size: 16px; + } + /* Header-Bereich */ .mindmap-header { position: absolute; @@ -369,115 +409,35 @@ {% block content %}