From 2a246ee0630fc2b972f1852f18aa3da329653b44 Mon Sep 17 00:00:00 2001 From: marwin Date: Fri, 16 May 2025 20:29:48 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20Verbesserung=20der=20Mindma?= =?UTF-8?q?p-Funktionalit=C3=A4t=20durch=20Einf=C3=BChrung=20von=20Unterse?= =?UTF-8?q?iten=20und=20Anpassung=20des=20Designs=20in=20update=5Fmindmap.?= =?UTF-8?q?js;=20Protokollaktualisierungen=20und=20Cache-Optimierungen=20v?= =?UTF-8?q?orgenommen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/app.cpython-313.pyc | Bin 118216 -> 118216 bytes logs/app.log | 27 ++ static/js/update_mindmap.js | 463 ++++++++++++++++++++++++-------- 3 files changed, 384 insertions(+), 106 deletions(-) diff --git a/__pycache__/app.cpython-313.pyc b/__pycache__/app.cpython-313.pyc index fd212152fc2ef5e8e75df9c390e26f72853e949d..559e1ca4b7d3d4849197a75c0e79bbf9cd70931f 100644 GIT binary patch delta 23 dcmX>xoBhOWcFxbdyj%=Gu(pwND<|XrvjALo2X_Df delta 23 dcmX>xoBhOWcFxbdyj%=GkkQDwm6LJ*SpZs32QmNv diff --git a/logs/app.log b/logs/app.log index dbbb937..a026c04 100644 --- a/logs/app.log +++ b/logs/app.log @@ -527,3 +527,30 @@ werkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on 2025-05-16 20:14:28,029 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] 2025-05-16 20:14:30,609 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] 2025-05-16 20:14:30,609 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:06,513 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:06,751 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:06,849 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:09,681 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:09,681 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:10,012 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:10,012 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:10,051 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:15:10,051 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:19:27,010 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:19:28,824 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:19:28,824 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:19:34,972 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:19:36,623 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:19:36,623 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:24:40,544 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:24:42,585 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:24:42,585 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:24:49,486 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:24:51,109 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:24:51,109 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:28:41,079 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:28:43,040 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:28:43,040 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:28:49,108 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:28:50,916 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] +2025-05-16 20:28:50,916 INFO: Anwendung gestartet [in C:\Users\firem\Desktop\111\Systades\website\app.py:77] diff --git a/static/js/update_mindmap.js b/static/js/update_mindmap.js index 05d563d..57a1eb7 100644 --- a/static/js/update_mindmap.js +++ b/static/js/update_mindmap.js @@ -1761,79 +1761,107 @@ document.head.appendChild(editingStyles); (function() { const style = document.createElement('style'); style.textContent = ` - .mindmap-page { + .mindmap-subpage { position: absolute; top: 0; left: 0; width: 100%; height: 100%; - background: linear-gradient(135deg, #1a1f2e 0%, #0f172a 100%); z-index: 1000; display: flex; flex-direction: column; + background: var(--bg-primary, linear-gradient(135deg, #1a1f2e 0%, #0f172a 100%)); } - .mindmap-page .mindmap-header { - position: relative; + .mindmap-subpage .subpage-header { display: flex; align-items: center; - padding: 1rem; - background: rgba(15, 23, 42, 0.8); + gap: 12px; + padding: 16px; + background: rgba(15, 23, 42, 0.9); backdrop-filter: blur(10px); border-bottom: 1px solid rgba(255, 255, 255, 0.1); z-index: 10; - height: 64px; } - .mindmap-page .back-button { - background: none; + .mindmap-subpage .back-button { + background: rgba(255, 255, 255, 0.1); border: none; - color: #fff; - cursor: pointer; - padding: 0.5rem; - margin-right: 1rem; + color: white; + width: 40px; + height: 40px; border-radius: 50%; - transition: background-color 0.3s; display: flex; align-items: center; justify-content: center; - width: 36px; - height: 36px; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } - .mindmap-page .back-button:hover { - background: rgba(255, 255, 255, 0.1); + .mindmap-subpage .back-button:hover { + background: rgba(255, 255, 255, 0.2); + transform: translateY(-2px); } - .mindmap-page .back-button svg { - width: 20px; - height: 20px; - } - - .mindmap-page .mindmap-title { - color: #fff; + .mindmap-subpage .subpage-title { font-size: 1.5rem; font-weight: 600; + color: white; margin: 0; background: linear-gradient(90deg, #60a5fa, #8b5cf6); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } - .mindmap-view { + .mindmap-subpage .subpage-cy-container { + flex: 1; width: 100%; - height: calc(100% - 64px); + height: calc(100% - 72px); position: relative; } - /* Fix für den Cytoscape Container */ - .mindmap-view > div { - width: 100%; - height: 100%; - background: transparent; + .mindmap-subpage .mindmap-toolbar { position: absolute; - top: 0; - left: 0; + top: 20px; + 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-subpage .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-subpage .mindmap-toolbar button:hover { + background: rgba(139, 92, 246, 0.5); + transform: translateY(-2px); + } + + .mindmap-subpage .mindmap-toolbar button i { + font-size: 16px; + } + + .dark .mindmap-subpage { + background: linear-gradient(135deg, #0f172a 0%, #0c1221 100%); } `; document.head.appendChild(style); @@ -1856,93 +1884,293 @@ async function loadSubthemes(node) { } // Erstelle eine neue Seite für die Unterkategorien - const newPage = document.createElement('div'); - newPage.className = 'mindmap-page'; - newPage.style.display = 'none'; + const subpage = document.createElement('div'); + subpage.className = 'mindmap-subpage'; + // Erstelle den Header mit Zurück-Button und Titel const header = document.createElement('div'); - header.className = 'mindmap-header'; + header.className = 'subpage-header'; header.innerHTML = ` -

${node.data('label')}

+

${node.data('label') || node.data('name')}

`; - const newContainer = document.createElement('div'); - newContainer.id = `cy-${node.id()}`; - newContainer.className = 'mindmap-view'; + // Erstelle den Container für die Cytoscape-Instanz + const cyContainer = document.createElement('div'); + cyContainer.className = 'subpage-cy-container'; + cyContainer.id = `cy-${node.id()}`; - // Füge die Elemente zur DOM-Struktur hinzu - newPage.appendChild(header); - newPage.appendChild(newContainer); - mindmapContainer.appendChild(newPage); + // Erstelle die Toolbar + const toolbar = document.createElement('div'); + toolbar.className = 'mindmap-toolbar'; + toolbar.innerHTML = ` + + + + `; + + // Füge alle Elemente zum DOM hinzu + cyContainer.appendChild(toolbar); + subpage.appendChild(header); + subpage.appendChild(cyContainer); + mindmapContainer.appendChild(subpage); // Warte, bis der DOM aktualisiert ist - await new Promise(resolve => setTimeout(resolve, 50)); + await new Promise(resolve => setTimeout(resolve, 10)); + + // Verstecke die Hauptseite und zeige die Unterseite an + cy.container().style.display = 'none'; // Speichere die Cytoscape-Instanz für eventuelle Referenzen if (!window.subthemeCyInstances) { window.subthemeCyInstances = {}; } - // Überprüfe, ob der Container jetzt im DOM existiert - const containerElement = document.getElementById(`cy-${node.id()}`); - if (!containerElement) { - console.error(`Container #cy-${node.id()} nicht gefunden`); - showUINotification(`Fehler: Container #cy-${node.id()} nicht gefunden`, 'error'); - return; - } + // Erstelle ein Array mit den Knoten-Elementen + const elements = []; - // Erstelle die Cytoscape-Instanz - const newCy = cytoscape({ - container: containerElement, - elements: [ - ...mindmapData.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: 16 - } - })), - ...mindmapData.edges.map(edge => ({ - data: { - source: edge.source, - target: edge.target, - strength: edge.strength || 0.5 - } - })) - ], - style: cy.style(), - layout: mindmapStyles.layout.base + // Knoten mit angepassten Daten für neuronale Eigenschaften + mindmapData.nodes.forEach(node => { + const isCenter = node.is_center || false; + elements.push({ + group: 'nodes', + 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: isCenter ? 20 : 16, + isCenter: isCenter, + neuronSize: isCenter ? 12 : 8, + neuronActivity: isCenter ? 1.0 : 0.8, + refractionPeriod: Math.random() * 300 + 700, + threshold: Math.random() * 0.3 + 0.6, + lastFired: 0 + } + }); }); - // Speichere die Cytoscape-Instanz + // Kanten mit angepassten Daten für neuronale Eigenschaften + mindmapData.edges.forEach(edge => { + elements.push({ + group: 'edges', + data: { + source: edge.source, + target: edge.target, + strength: edge.strength || 0.5, + conductionVelocity: Math.random() * 0.5 + 0.3, + latency: Math.random() * 100 + 50 + } + }); + }); + + // Erstelle die neue Cytoscape-Instanz + const newCy = cytoscape({ + container: document.getElementById(`cy-${node.id()}`), + elements: elements, + style: [ + { + selector: 'node', + style: { + 'label': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'color': 'data(fontColor)', + 'text-outline-width': 2, + 'text-outline-color': 'rgba(0,0,0,0.8)', + 'text-outline-opacity': 0.9, + 'font-size': 'data(fontSize)', + 'font-weight': '500', + 'text-margin-y': 8, + 'width': function(ele) { + if (ele.data('isCenter')) return 120; + return 80; + }, + 'height': function(ele) { + if (ele.data('isCenter')) return 120; + return 80; + }, + 'background-color': 'data(color)', + 'background-opacity': 0.9, + 'border-width': 2, + 'border-color': '#ffffff', + 'border-opacity': 0.8, + 'shape': 'ellipse', + 'shadow-blur': 15, + 'shadow-color': 'data(color)', + 'shadow-opacity': 0.6, + 'shadow-offset-x': 0, + 'shadow-offset-y': 0, + 'transition-property': 'background-color, background-opacity, border-width, shadow-opacity', + 'transition-duration': '0.3s', + 'transition-timing-function': 'ease-in-out' + } + }, + { + selector: 'edge', + style: { + 'width': function(ele) { + return ele.data('strength') ? ele.data('strength') * 3 : 1; + }, + 'curve-style': 'bezier', + '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.8 : 0.4; + }, + 'line-style': function(ele) { + const strength = ele.data('strength'); + if (!strength) return 'solid'; + if (strength <= 0.4) return 'dotted'; + if (strength <= 0.6) return 'dashed'; + return 'solid'; + }, + 'target-arrow-shape': 'none', + 'source-endpoint': '0% 50%', + 'target-endpoint': '100% 50%', + 'transition-property': 'line-opacity, width', + 'transition-duration': '0.3s', + 'transition-timing-function': 'ease-in-out' + } + } + ], + layout: { + name: 'cose', + animate: true, + animationDuration: 800, + refresh: 20, + fit: true, + padding: 50, + nodeRepulsion: 8000, + idealEdgeLength: 75, + edgeElasticity: 0.45, + randomize: false, + componentSpacing: 120, + nodeOverlap: 20, + gravity: 0.4, + initialTemp: 800, + coolingFactor: 0.95, + minTemp: 1 + }, + wheelSensitivity: 0.3 + }); + + // Speichere die Instanz window.subthemeCyInstances[node.id()] = newCy; - // Event-Listener für die neue Mindmap + // Zeige die Subpage an + subpage.style.display = 'flex'; + + // Event-Listener für Knoten hinzufügen newCy.on('tap', 'node', async function(evt) { const clickedNode = evt.target; + + // Alle vorherigen Hervorhebungen zurücksetzen + newCy.nodes().forEach(n => { + n.removeStyle(); + n.connectedEdges().removeStyle(); + }); + + // Aktiviere leuchtenden Effekt + clickedNode.style({ + 'background-opacity': 1, + 'background-color': clickedNode.data('color'), + 'shadow-color': clickedNode.data('color'), + 'shadow-opacity': 1, + 'shadow-blur': 15, + 'shadow-offset-x': 0, + 'shadow-offset-y': 0 + }); + + // Verbundene Kanten und Knoten hervorheben + const connectedEdges = clickedNode.connectedEdges(); + const connectedNodes = clickedNode.neighborhood('node'); + + connectedEdges.style({ + 'line-color': '#a78bfa', + 'target-arrow-color': '#a78bfa', + 'source-arrow-color': '#a78bfa', + 'line-opacity': 0.8, + 'width': 2 + }); + + connectedNodes.style({ + 'shadow-opacity': 0.7, + 'shadow-blur': 10, + 'shadow-color': '#a78bfa' + }); + + // Wenn der Knoten Unterkategorien hat und nicht erweitert ist, lade die Unterkategorien if (clickedNode.data('hasChildren') && !clickedNode.data('expanded')) { await loadSubthemes(clickedNode); } }); - // Alte Seite ausblenden und neue anzeigen - cy.container().style.display = 'none'; - newPage.style.display = 'block'; + // Klick auf Hintergrund - Auswahl zurücksetzen + newCy.on('tap', function(evt) { + if (evt.target === newCy) { + newCy.nodes().forEach(n => { + n.removeStyle(); + n.connectedEdges().removeStyle(); + }); + } + }); - // Wende neuronales Design auf die neue Mindmap an - applyNeuralNetworkStyle(newCy); + // Zoom-Controls für die Unterkategorien + document.getElementById(`zoomIn-${node.id()}`)?.addEventListener('click', () => { + newCy.zoom({ + level: newCy.zoom() * 1.2, + renderedPosition: { x: newCy.width() / 2, y: newCy.height() / 2 } + }); + }); + document.getElementById(`zoomOut-${node.id()}`)?.addEventListener('click', () => { + newCy.zoom({ + level: newCy.zoom() / 1.2, + renderedPosition: { x: newCy.width() / 2, y: newCy.height() / 2 } + }); + }); + + document.getElementById(`resetView-${node.id()}`)?.addEventListener('click', () => { + newCy.fit(); + newCy.nodes().forEach(n => { + n.removeStyle(); + n.connectedEdges().removeStyle(); + }); + }); + + // Hervorhebe den zentralen Knoten + newCy.nodes().forEach(node => { + if (node.data('isCenter')) { + node.style({ + 'background-opacity': 1, + 'border-width': 3, + 'shadow-blur': 20, + 'shadow-opacity': 0.8 + }); + } + }); + + // Wende neuronale Simulationen an + startNeuralActivitySimulation(newCy); + + // Erfolgsbenachrichtigung showUINotification('Subthemen erfolgreich geladen', 'success'); } catch (error) { @@ -1955,27 +2183,50 @@ async function loadSubthemes(node) { function goBack() { try { console.log('goBack Funktion aufgerufen'); - const currentPage = document.querySelector('.mindmap-page:not([style*="display: none"])'); - if (currentPage) { - console.log('Aktuelle Seite gefunden:', currentPage); - currentPage.style.display = 'none'; + const subpage = document.querySelector('.mindmap-subpage'); + if (subpage) { + console.log('Unterseite gefunden:', subpage); - // Stelle sicher, dass die Haupt-Cytoscape-Instanz existiert - if (window.cy && window.cy.container()) { - console.log('Zeige Haupt-Cytoscape-Container an'); - window.cy.container().style.display = 'block'; + // Entferne die Unterseite mit Animation + subpage.style.opacity = '0'; + subpage.style.transform = 'translateY(20px)'; + + setTimeout(() => { + if (subpage.parentNode) { + subpage.parentNode.removeChild(subpage); + } - // Aktualisiere das Layout - setTimeout(() => { - window.cy.resize(); - window.cy.fit(); - }, 100); - } else { - console.error('Haupt-Cytoscape-Instanz oder Container nicht gefunden'); - showUINotification('Fehler: Hauptmindmap konnte nicht angezeigt werden', 'error'); - } + // Stelle sicher, dass die Haupt-Cytoscape-Instanz existiert + if (window.cy && window.cy.container()) { + console.log('Zeige Haupt-Cytoscape-Container an'); + window.cy.container().style.display = 'block'; + + // Aktualisiere das Layout + setTimeout(() => { + window.cy.resize(); + window.cy.fit(); + }, 100); + } else { + console.error('Haupt-Cytoscape-Instanz oder Container nicht gefunden'); + showUINotification('Fehler: Hauptmindmap konnte nicht angezeigt werden', 'error'); + } + }, 200); } else { console.warn('Keine aktuelle Unterseite gefunden'); + + // Fallback: Versuche die alte mindmap-page zu finden + const oldPage = document.querySelector('.mindmap-page'); + if (oldPage) { + oldPage.style.display = 'none'; + + if (window.cy && window.cy.container()) { + window.cy.container().style.display = 'block'; + setTimeout(() => { + window.cy.resize(); + window.cy.fit(); + }, 100); + } + } } } catch (error) { console.error('Fehler in goBack Funktion:', error);