chore: Änderungen commited

This commit is contained in:
2025-05-14 11:39:58 +02:00
parent 3aefe6c5e6
commit 2b19cb000b
2 changed files with 126 additions and 619 deletions

View File

@@ -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]

View File

@@ -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';
}
// Nachrichteninhalt formatieren
let content = '';
// 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');
if (typeof message === 'object' && message !== null) {
// Wenn es ein Fehler-Objekt ist
if (message.error) {
content = message.error;
if (message.details) {
content += `<br><small>${message.details}</small>`;
}
// 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 = `
<button class="back-button" onclick="goBack()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M19 12H5M12 19l-7-7 7-7"/>
</svg>
</button>
<h2 class="mindmap-title">${node.data('label')}</h2>
<div class="mindmap-actions">
<button class="edit-button" onclick="enableMindmapEditing('${node.id()}')">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
<span>Bearbeiten</span>
</button>
</div>
`;
// 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 = '&times;';
closeButton.style.position = 'absolute';
// Deaktiviere Bearbeitungsfunktionen
cy.nodes().grabify();
cy.container().classList.remove('editing-mode');