diff --git a/logs/app.log b/logs/app.log index 82ed580..a6e15b0 100644 --- a/logs/app.log +++ b/logs/app.log @@ -14,3 +14,54 @@ 2025-05-14 11:23:02,222 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] 2025-05-14 11:23:04,911 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] 2025-05-14 11:23:04,911 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:23:30,306 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:23:32,842 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:23:32,842 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:24:05,060 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:24:07,477 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:24:07,477 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:24:11,604 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:24:14,428 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:24:14,428 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:25:57,023 ERROR: Fehler 404: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again. +Endpoint: /.well-known/appspecific/com.chrome.devtools.json, Method: GET, IP: 127.0.0.1 +Nicht angemeldet +Traceback (most recent call last): + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\app.py", line 1484, in full_dispatch_request + rv = self.dispatch_request() + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\app.py", line 1458, in dispatch_request + self.raise_routing_exception(req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^ + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\app.py", line 1440, in raise_routing_exception + raise request.routing_exception # type: ignore + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\ctx.py", line 353, in match_request + result = self.url_adapter.match(return_rule=True) # type: ignore + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\werkzeug\routing\map.py", line 655, in match + raise NotFound() from None +werkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again. + [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:93] +2025-05-14 11:25:57,023 ERROR: Fehler 404: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again. +Endpoint: /.well-known/appspecific/com.chrome.devtools.json, Method: GET, IP: 127.0.0.1 +Nicht angemeldet +Traceback (most recent call last): + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\app.py", line 1484, in full_dispatch_request + rv = self.dispatch_request() + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\app.py", line 1458, in dispatch_request + self.raise_routing_exception(req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^ + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\app.py", line 1440, in raise_routing_exception + raise request.routing_exception # type: ignore + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\flask\ctx.py", line 353, in match_request + result = self.url_adapter.match(return_rule=True) # type: ignore + File "C:\Users\TTOMCZA.EMEA\AppData\Roaming\Python\Python313\site-packages\werkzeug\routing\map.py", line 655, in match + raise NotFound() from None +werkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again. + [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:93] +2025-05-14 11:27:26,252 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:27:26,419 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:27:28,763 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:27:28,763 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:27:28,854 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] +2025-05-14 11:27:28,854 INFO: Anwendung gestartet [in C:\Users\TTOMCZA.EMEA\Dev\website\app.py:77] diff --git a/static/js/update_mindmap.js b/static/js/update_mindmap.js index 419cf71..c1cd5b8 100644 --- a/static/js/update_mindmap.js +++ b/static/js/update_mindmap.js @@ -136,11 +136,7 @@ async function loadMindmapData(nodeId = null) { let errorData; try { errorData = await response.json(); - console.log('API-Fehler Details:', { - status: response.status, - statusText: response.statusText, - errorData - }); + console.log('API-Fehler Details:', errorData); } catch (e) { console.error('Fehler beim Parsen der Fehlerantwort:', e); errorData = { @@ -149,25 +145,26 @@ async function loadMindmapData(nodeId = null) { } // Fehlerobjekt für die Benachrichtigung erstellen - const errorMessage = { - error: errorData.error || errorData.message || 'Unbekannter Fehler', - details: errorData.details || null - }; + const errorMessage = errorData.error || 'Unbekannter Fehler'; showUINotification(errorMessage, 'error'); - throw new Error(errorMessage.error); + throw new Error(errorMessage); } const data = await response.json(); console.log('Geladene Mindmap-Daten:', data); if (!data.success) { - const errorMessage = { - error: data.error || 'Mindmap-Daten konnten nicht geladen werden', - details: data.details || null - }; + const errorMessage = data.error || 'Mindmap-Daten konnten nicht geladen werden'; showUINotification(errorMessage, 'error'); - throw new Error(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 @@ -175,17 +172,10 @@ async function loadMindmapData(nodeId = null) { showUINotification('Mindmap-Daten erfolgreich geladen', 'success'); return data; } catch (error) { - console.error('Fehler beim Laden der Mindmap-Daten:', { - message: error.message, - stack: error.stack, - nodeId - }); + console.error('Fehler beim Laden der Mindmap-Daten:', error); // Stelle sicher, dass wir eine aussagekräftige Fehlermeldung haben - const errorMessage = { - error: error.message || 'Unbekannter Fehler beim Laden der Mindmap-Daten', - details: error.stack - }; + const errorMessage = error.message || 'Unbekannter Fehler beim Laden der Mindmap-Daten'; showUINotification(errorMessage, 'error'); throw error; @@ -754,609 +744,75 @@ function showFlash(message, type = 'info') { * @param {number} duration - Die Anzeigedauer in Millisekunden (Standard: 3000) */ function showUINotification(message, type = 'info', duration = 3000) { - // Überprüfe und formatiere die Nachricht - let displayMessage; - if (typeof message === 'object') { - if (message.message) { - displayMessage = message.message; - } else if (message.error) { - displayMessage = message.error; - } else if (message.details) { - displayMessage = message.details; - } else { - console.error('Ungültiges Nachrichtenobjekt:', message); - displayMessage = 'Ein unbekannter Fehler ist aufgetreten'; - } - } else if (typeof message === 'string') { - displayMessage = message; + // Container erstellen, falls er nicht existiert + let container = document.getElementById('notification-container'); + if (!container) { + container = document.createElement('div'); + container.id = 'notification-container'; + container.style.position = 'fixed'; + container.style.top = '1rem'; + container.style.right = '1rem'; + container.style.zIndex = '1000'; + container.style.maxWidth = '400px'; + document.body.appendChild(container); + } + + // Benachrichtigung erstellen + const notification = document.createElement('div'); + notification.className = `notification notification-${type}`; + notification.style.padding = '1rem'; + notification.style.marginBottom = '0.5rem'; + notification.style.borderRadius = '0.25rem'; + notification.style.boxShadow = '0 2px 5px rgba(0, 0, 0, 0.2)'; + notification.style.position = 'relative'; + notification.style.opacity = '0'; + notification.style.transform = 'translateY(-20px)'; + notification.style.transition = 'all 0.3s ease-in-out'; + + // Farben nach Typ + if (type === 'success') { + notification.style.backgroundColor = '#059669'; + notification.style.color = '#ffffff'; + } else if (type === 'error') { + notification.style.backgroundColor = '#DC2626'; + notification.style.color = '#ffffff'; + } else if (type === 'warning') { + notification.style.backgroundColor = '#F59E0B'; + notification.style.color = '#ffffff'; } else { - console.error('Ungültige Nachricht für UI-Benachrichtigung:', message); - displayMessage = 'Ein unbekannter Fehler ist aufgetreten'; + notification.style.backgroundColor = '#3B82F6'; + notification.style.color = '#ffffff'; } - - // Validiere den Typ - const validTypes = ['info', 'success', 'warning', 'error']; - if (!validTypes.includes(type)) { - console.warn(`Ungültiger Benachrichtigungstyp: ${type}. Verwende 'info' als Fallback.`); - type = 'info'; - } - - // Validiere die Dauer - if (typeof duration !== 'number' || duration < 1000 || duration > 10000) { - console.warn(`Ungültige Dauer: ${duration}ms. Verwende 3000ms als Fallback.`); - duration = 3000; - } - - // Zeige die Benachrichtigung an - showFlash(displayMessage, type); - - // Logging für Debugging-Zwecke - console.log(`UI-Benachrichtigung [${type}]:`, displayMessage); -} - -// Hilfsfunktion zum Erstellen eines Flash-Containers, falls keiner existiert -function createFlashContainer() { - const container = document.createElement('div'); - container.id = 'flash-messages'; - container.className = 'fixed top-4 right-4 z-50 w-64'; - document.body.appendChild(container); - return container; -} - -// Funktion zum Laden der Subthemen -async function loadSubthemes(node) { - try { - // Prüfe zuerst, ob die Node gültig ist - if (!node || !node.id) { - console.error('Ungültige Node beim Laden der Subthemen'); - showUINotification('Fehler: Ungültiger Knoten für Subthemen', 'error'); - return; - } - - // Zeige Ladebenachrichtigung - showUINotification('Lade Subthemen...', 'info'); - console.log('Lade Subthemen für Node:', node.id()); - - // Lade die Daten für die Unterthemen - const data = await loadMindmapData(node.id()); - if (!data || !data.nodes || !data.edges) { - throw new Error('Ungültiges Datenformat: Subthemen-Daten fehlen oder sind unvollständig'); - } - - // Markiere den aktuellen Knoten als erweitert - node.data('expanded', true); - - // Finde den Mindmap-Container - let mindmapContainer = document.querySelector('.mindmap-container'); - if (!mindmapContainer) { - // Falls der Container nicht existiert, versuche den cy-Container zu finden und erstelle einen Wrapper - const cyContainer = document.getElementById('cy'); - if (!cyContainer) { - throw new Error('Mindmap-Container nicht gefunden'); + + // Nachrichteninhalt formatieren + let content = ''; + + if (typeof message === 'object' && message !== null) { + // Wenn es ein Fehler-Objekt ist + if (message.error) { + content = message.error; + if (message.details) { + content += `
${message.details}`; } - - // Erstelle einen Container für die Mindmap-Seiten - const parentElement = cyContainer.parentElement; - mindmapContainer = document.createElement('div'); - mindmapContainer.className = 'mindmap-container'; - parentElement.insertBefore(mindmapContainer, cyContainer); - parentElement.removeChild(cyContainer); - mindmapContainer.appendChild(cyContainer); - } - - // Erstelle eine neue Seite für die Unterthemen - const newPage = document.createElement('div'); - newPage.className = 'mindmap-page'; - newPage.setAttribute('data-parent-node', node.id()); - - // Erstelle den Header der Seite - const header = document.createElement('div'); - header.className = 'mindmap-header'; - header.innerHTML = ` - -

${node.data('label')}

-
- -
- `; - - // Erstelle den Container für das neue Cytoscape - const newCyContainer = document.createElement('div'); - newCyContainer.id = `cy-${node.id()}`; - newCyContainer.className = 'mindmap-view'; - - // Füge die Elemente zur Seite hinzu - newPage.appendChild(header); - newPage.appendChild(newCyContainer); - mindmapContainer.appendChild(newPage); - - // Aktuelles Cy-Element ausblenden - if (cy && cy.container()) { - cy.container().style.display = 'none'; - } - - // Initialisiere das neue Cytoscape - const newCy = cytoscape({ - container: newCyContainer, - elements: [ - // Knoten - ...data.nodes.map(node => ({ - data: { - id: node.id, - label: node.name || node.label, - category: node.category, - description: node.description, - hasChildren: node.has_children, - expanded: false, - color: node.color_code || (node.category && mindmapConfig.categories[node.category] - ? mindmapConfig.categories[node.category].color - : '#60a5fa'), - fontColor: '#ffffff', - fontSize: 16 - } - })), - // Kanten - ...data.edges.map(edge => ({ - data: { - source: edge.source || edge.source_id, - target: edge.target || edge.target_id, - strength: edge.strength || 0.5 - } - })) - ], - 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 - }); - - // Füge neuronale Eigenschaften zu allen Knoten hinzu - newCy.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 - newCy.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 die neue Mindmap - newCy.on('tap', 'node', async function(evt) { - const clickedNode = evt.target; - console.log('Node clicked in subtheme:', clickedNode.id(), 'hasChildren:', clickedNode.data('hasChildren'), 'expanded:', clickedNode.data('expanded')); - - if (clickedNode.data('hasChildren') && !clickedNode.data('expanded')) { - await loadSubthemes(clickedNode); - } - }); - - // Starte neuronale Aktivitätssimulation für die neue Mindmap - startNeuralActivitySimulation(newCy); - - // Speichere die Cytoscape-Instanz in einem globalen Array, damit wir sie später referenzieren können - if (!window.subthemeCyInstances) { - window.subthemeCyInstances = {}; - } - window.subthemeCyInstances[node.id()] = newCy; - - // Layout ausführen - newCy.layout(mindmapStyles.layout.base).run(); - - // Zeige die neue Seite an - newPage.style.display = 'block'; - - showUINotification('Subthemen erfolgreich geladen', 'success'); - return true; - } catch (error) { - console.error('Fehler beim Laden der Subthemen:', error); - showUINotification({ - error: 'Subthemen konnten nicht geladen werden', - details: error.message - }, 'error'); - return false; - } -} - -// Funktion zum Zurücknavigieren -function goBack() { - try { - // Finde die aktuell angezeigte Mindmap-Seite - const currentPage = document.querySelector('.mindmap-page:not([style*="display: none"])'); - if (!currentPage) { - console.warn('Keine Mindmap-Seite gefunden, zu der zurückgekehrt werden kann'); - return; - } - - // Finde die übergeordnete Node ID - const parentNodeId = currentPage.getAttribute('data-parent-node'); - if (!parentNodeId) { - console.warn('Keine übergeordnete Node-ID gefunden, zeige die Hauptmindmap an'); - - // Blende das aktuelle Cy-Element aus - if (window.cy && window.cy.container()) { - window.cy.container().style.display = 'block'; - } - - // Entferne die aktuelle Seite - currentPage.style.display = 'none'; - setTimeout(() => { - if (currentPage.parentNode) { - currentPage.parentNode.removeChild(currentPage); - } - }, 300); - - return; - } - - console.log('Navigiere zurück von Knoten:', parentNodeId); - - // Entferne die aktuelle Cytoscape-Instanz aus dem Array - if (window.subthemeCyInstances && window.subthemeCyInstances[parentNodeId]) { + } else { + // Versuche, das Objekt zu stringifizieren try { - if (typeof window.subthemeCyInstances[parentNodeId].destroy === 'function') { - window.subthemeCyInstances[parentNodeId].destroy(); - } - delete window.subthemeCyInstances[parentNodeId]; + content = JSON.stringify(message); } catch (e) { - console.error('Fehler beim Zerstören der Cytoscape-Instanz:', e); + content = 'Objekt konnte nicht angezeigt werden'; } } - - // Prüfe, ob es eine übergeordnete Mindmap-Seite gibt - const parentPage = document.querySelector(`.mindmap-page[data-parent-node]:not([data-parent-node="${parentNodeId}"])`); - - if (parentPage) { - // Wenn eine übergeordnete Seite gefunden wurde, zeige sie an - parentPage.style.display = 'block'; - - // Entferne die aktuelle Seite - currentPage.style.display = 'none'; - setTimeout(() => { - if (currentPage.parentNode) { - currentPage.parentNode.removeChild(currentPage); - } - }, 300); - } else { - // Wenn keine übergeordnete Seite gefunden wurde, zeige die Hauptmindmap an - if (window.cy && window.cy.container()) { - window.cy.container().style.display = 'block'; - } - - // Entferne die aktuelle Seite - currentPage.style.display = 'none'; - setTimeout(() => { - if (currentPage.parentNode) { - currentPage.parentNode.removeChild(currentPage); - } - }, 300); - } - - showUINotification('Zurück zur übergeordneten Mindmap', 'info'); - } catch (error) { - console.error('Fehler bei der Rücknavigation:', error); - showUINotification('Fehler bei der Rücknavigation', 'error'); - } -} - -// CSS-Styles für die neue Seite -const style = document.createElement('style'); -style.textContent = ` - .mindmap-page { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: var(--bg-color, #1a1a1a); - z-index: 1000; - } - - .mindmap-header { - display: flex; - align-items: center; - padding: 1rem; - background: rgba(0, 0, 0, 0.2); - border-bottom: 1px solid rgba(255, 255, 255, 0.1); - } - - .back-button { - background: none; - border: none; - color: #fff; - cursor: pointer; - padding: 0.5rem; - margin-right: 1rem; - border-radius: 50%; - transition: background-color 0.3s; - } - - .back-button:hover { - background: rgba(255, 255, 255, 0.1); - } - - .mindmap-title { - color: #fff; - font-size: 1.5rem; - font-weight: 600; - margin: 0; - } - - .mindmap-view { - width: 100%; - height: calc(100% - 4rem); - } - - /* Neuronale Effekte */ - .cy-container { - background: linear-gradient(45deg, #1a1a1a, #2a2a2a); - } - - .cy-container node { - transition: all 0.3s ease; - } - - .cy-container node:hover { - filter: brightness(1.2); - } - - .cy-node-icon { - position: absolute; - pointer-events: none; - z-index: 1001; - color: #fff; - text-shadow: 0 2px 8px rgba(0,0,0,0.25); - } - - /* Verbesserte Flash-Benachrichtigungen */ - #flash-messages { - position: fixed; - top: 1rem; - right: 1rem; - z-index: 9999; - display: flex; - flex-direction: column; - gap: 0.5rem; - max-width: 24rem; - } - - .flash-message { - padding: 1rem 1.25rem; - border-radius: 0.5rem; - background: rgba(17, 24, 39, 0.95); - color: #fff; - font-size: 0.875rem; - line-height: 1.25rem; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), - 0 2px 4px -1px rgba(0, 0, 0, 0.06); - transform: translateX(120%); - opacity: 0; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - backdrop-filter: blur(8px); - border: 1px solid rgba(255, 255, 255, 0.1); - } - - .flash-message.show { - transform: translateX(0); - opacity: 1; - } - - .flash-message.info { - border-left: 4px solid #3b82f6; - background: linear-gradient(to right, rgba(59, 130, 246, 0.1), rgba(17, 24, 39, 0.95)); - } - - .flash-message.success { - border-left: 4px solid #10b981; - background: linear-gradient(to right, rgba(16, 185, 129, 0.1), rgba(17, 24, 39, 0.95)); - } - - .flash-message.warning { - border-left: 4px solid #f59e0b; - background: linear-gradient(to right, rgba(245, 158, 11, 0.1), rgba(17, 24, 39, 0.95)); - } - - .flash-message.error { - border-left: 4px solid #ef4444; - background: linear-gradient(to right, rgba(239, 68, 68, 0.1), rgba(17, 24, 39, 0.95)); - } - - .flash-message::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient(45deg, - rgba(255, 255, 255, 0.1) 0%, - rgba(255, 255, 255, 0) 100%); - pointer-events: none; - } - - @keyframes pulse { - 0% { transform: scale(1); } - 50% { transform: scale(1.02); } - 100% { transform: scale(1); } - } - - .flash-message.show { - animation: pulse 0.3s ease-in-out; - } - - /* Neuronale Effekte für Benachrichtigungen */ - .flash-message.info:hover { - box-shadow: 0 0 15px rgba(59, 130, 246, 0.3); - } - - .flash-message.success:hover { - box-shadow: 0 0 15px rgba(16, 185, 129, 0.3); - } - - .flash-message.warning:hover { - box-shadow: 0 0 15px rgba(245, 158, 11, 0.3); - } - - .flash-message.error:hover { - box-shadow: 0 0 15px rgba(239, 68, 68, 0.3); - } -`; -document.head.appendChild(style); - -// Initialisiere die Mindmap beim Laden der Seite -document.addEventListener('DOMContentLoaded', initializeMindmap); - -// Funktion zum Aktivieren des Bearbeitungsmodus -function enableMindmapEditing(nodeId) { - try { - console.log('Aktiviere Bearbeitungsmodus für Mindmap:', nodeId); - - // Finde die relevante Cytoscape-Instanz - let targetCy; - if (nodeId) { - // Für Unterthemen - if (window.subthemeCyInstances && window.subthemeCyInstances[nodeId]) { - targetCy = window.subthemeCyInstances[nodeId]; - } else { - throw new Error(`Cytoscape-Instanz für Node ${nodeId} nicht gefunden`); - } - } else { - // Für die Hauptmindmap - targetCy = window.cy; - } - - if (!targetCy) { - throw new Error('Keine aktive Cytoscape-Instanz gefunden'); - } - - // Aktiviere Bearbeitungsmodus - toggleEditingMode(targetCy, true); - - // Zeige Bearbeitungssteuerungen an - showEditingControls(nodeId); - - showUINotification('Bearbeitungsmodus aktiviert', 'info'); - } catch (error) { - console.error('Fehler beim Aktivieren des Bearbeitungsmodus:', error); - showUINotification('Fehler beim Aktivieren des Bearbeitungsmodus', 'error'); - } -} - -// Funktion zum Deaktivieren des Bearbeitungsmodus -function disableMindmapEditing(nodeId) { - try { - console.log('Deaktiviere Bearbeitungsmodus für Mindmap:', nodeId); - - // Finde die relevante Cytoscape-Instanz - let targetCy; - if (nodeId) { - // Für Unterthemen - if (window.subthemeCyInstances && window.subthemeCyInstances[nodeId]) { - targetCy = window.subthemeCyInstances[nodeId]; - } - } else { - // Für die Hauptmindmap - targetCy = window.cy; - } - - if (!targetCy) { - throw new Error('Keine aktive Cytoscape-Instanz gefunden'); - } - - // Deaktiviere Bearbeitungsmodus - toggleEditingMode(targetCy, false); - - // Verstecke Bearbeitungssteuerungen - hideEditingControls(nodeId); - - showUINotification('Bearbeitungsmodus deaktiviert', 'info'); - } catch (error) { - console.error('Fehler beim Deaktivieren des Bearbeitungsmodus:', error); - showUINotification('Fehler beim Deaktivieren des Bearbeitungsmodus', 'error'); - } -} - -// Funktion zum Umschalten des Bearbeitungsmodus -function toggleEditingMode(cy, enabled) { - if (!cy) return; - - if (enabled) { - // Mache Knoten beweglich - cy.nodes().ungrabify(false); - - // Ändere den Cursor-Stil - cy.container().classList.add('editing-mode'); - - // Aktiviere Ziehen und Ablegen - cy.on('dragfree', 'node', function(event) { - const node = event.target; - console.log('Node verschoben:', node.id(), node.position()); - // Hier könnte man die neue Position in der Datenbank speichern - }); - - // Aktiviere Doppelklick zum Bearbeiten - cy.on('dblclick', 'node', function(event) { - const node = event.target; - editNodeProperties(node); - }); - - // Aktiviere Rechtsklick-Menü - cy.on('cxttap', 'node', function(event) { - const node = event.target; - showNodeContextMenu(node, event.renderedPosition); - }); - - // Aktiviere Rechtsklick auf leeren Bereich zum Hinzufügen neuer Knoten - cy.on('cxttap', function(event) { - if (event.target === cy) { - showAddNodeMenu(event.renderedPosition); - } - }); } else { + // String oder andere primitive Typen + content = message; + } + + notification.innerHTML = content; + + // Schließen-Button + const closeButton = document.createElement('span'); + closeButton.innerHTML = '×'; + closeButton.style.position = 'absolute'; // Deaktiviere Bearbeitungsfunktionen cy.nodes().grabify(); cy.container().classList.remove('editing-mode');