✨ feat: enhance UI and functionality for mindmap creation and profile pages
This commit is contained in:
@@ -417,4 +417,606 @@ function getDefaultStyles(darkMode = document.documentElement.classList.contains
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
class MindMap {
|
||||
constructor(selector, options = {}) {
|
||||
// Standardoptionen festlegen
|
||||
this.options = Object.assign({
|
||||
// Standard-Basisoptionen
|
||||
editable: false, // Ist die Mindmap editierbar?
|
||||
isUserLoggedIn: false, // Ist der Benutzer angemeldet?
|
||||
isPublicMap: true, // Handelt es sich um die öffentliche Mindmap?
|
||||
initialZoom: 1, // Anfängliche Zoom-Stufe
|
||||
fitViewOnInit: true, // Passt die Ansicht automatisch an
|
||||
minZoom: 0.2, // Minimale Zoom-Stufe
|
||||
maxZoom: 3, // Maximale Zoom-Stufe
|
||||
// Farbpalette für verschiedene Elemente
|
||||
colorPalette: {
|
||||
node: {
|
||||
default: '#8b5cf6', // Standard-Knotenfarbe
|
||||
selected: '#7c3aed', // Farbe für ausgewählte Knoten
|
||||
hover: '#6d28d9' // Farbe für Hover-Effekt
|
||||
},
|
||||
edge: {
|
||||
default: '#8b5cf6', // Standard-Kantenfarbe
|
||||
selected: '#7c3aed', // Farbe für ausgewählte Kanten
|
||||
hover: '#6d28d9' // Farbe für Hover-Effekt
|
||||
},
|
||||
text: {
|
||||
default: '#f3f4f6', // Standard-Textfarbe
|
||||
dark: '#1f2937', // Dunkle Textfarbe (für helle Hintergründe)
|
||||
light: '#f9fafb' // Helle Textfarbe (für dunkle Hintergründe)
|
||||
},
|
||||
background: {
|
||||
dark: '#111827', // Dunkler Hintergrund
|
||||
light: '#f9fafb' // Heller Hintergrund
|
||||
}
|
||||
},
|
||||
// Anpassbare Funktionen
|
||||
callbacks: {
|
||||
onNodeClick: null, // Callback für Knotenklick
|
||||
onEdgeClick: null, // Callback für Kantenklick
|
||||
onViewportChange: null, // Callback für Änderung der Ansicht
|
||||
onSelectionChange: null, // Callback für Änderung der Auswahl
|
||||
onLoad: null // Callback nach dem Laden der Mindmap
|
||||
}
|
||||
}, options);
|
||||
|
||||
// Container-Element
|
||||
this.container = document.querySelector(selector);
|
||||
if (!this.container) {
|
||||
console.error(`Container mit Selektor '${selector}' nicht gefunden`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfen, ob der Benutzer angemeldet ist
|
||||
this.isUserLoggedIn = document.body.classList.contains('user-logged-in') || this.options.isUserLoggedIn;
|
||||
|
||||
// Wenn der Benutzer angemeldet ist und es sich um die öffentliche Mindmap handelt,
|
||||
// wird die Editierbarkeit aktiviert
|
||||
if (this.isUserLoggedIn && this.options.isPublicMap) {
|
||||
this.options.editable = true;
|
||||
}
|
||||
|
||||
// Initialisiere Cytoscape
|
||||
this.initCytoscape();
|
||||
|
||||
// Füge Bearbeiten-Funktionalität hinzu, wenn editierbar
|
||||
if (this.options.editable) {
|
||||
this.initEditableMode();
|
||||
}
|
||||
|
||||
// Lade Daten basierend auf dem Typ der Mindmap
|
||||
if (this.options.isPublicMap) {
|
||||
this.loadPublicMindmap();
|
||||
} else if (this.options.userMindmapId) {
|
||||
this.loadUserMindmap(this.options.userMindmapId);
|
||||
}
|
||||
|
||||
// Initialisiere UI-Elemente
|
||||
this.initUI();
|
||||
|
||||
// Event-Listener-Initialisierung
|
||||
this.initEventListeners();
|
||||
|
||||
// Flash-Message-System
|
||||
this.flashContainer = null;
|
||||
this.initFlashMessages();
|
||||
}
|
||||
|
||||
// ... existing code ...
|
||||
|
||||
// Initialisiert die Bearbeitungsmodi für die Mindmap
|
||||
initEditableMode() {
|
||||
// Toolbar für Bearbeitungsmodus hinzufügen
|
||||
this.addEditToolbar();
|
||||
|
||||
// Kontextmenü-Funktionalität für Knoten
|
||||
this.cy.on('cxttap', 'node', (evt) => {
|
||||
const node = evt.target;
|
||||
const position = evt.renderedPosition;
|
||||
|
||||
// Zeige Kontextmenü
|
||||
this.showNodeContextMenu(node, position);
|
||||
});
|
||||
|
||||
// Doppelklick-Funktion für das Hinzufügen neuer Knoten
|
||||
this.cy.on('dblclick', (evt) => {
|
||||
// Nur auf Hintergrund reagieren, nicht auf Knoten
|
||||
if (evt.target === this.cy) {
|
||||
const position = evt.position;
|
||||
this.showAddNodeDialog(position);
|
||||
}
|
||||
});
|
||||
|
||||
// Kontextmenü-Schließen bei Klick außerhalb
|
||||
document.addEventListener('click', (e) => {
|
||||
const contextMenu = document.getElementById('context-menu');
|
||||
if (contextMenu && !contextMenu.contains(e.target)) {
|
||||
contextMenu.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Zeigt ein Kontextmenü für einen Knoten an
|
||||
showNodeContextMenu(node, position) {
|
||||
// Entferne vorhandenes Kontextmenü
|
||||
const existingMenu = document.getElementById('context-menu');
|
||||
if (existingMenu) existingMenu.remove();
|
||||
|
||||
// Erstelle neues Kontextmenü
|
||||
const contextMenu = document.createElement('div');
|
||||
contextMenu.id = 'context-menu';
|
||||
contextMenu.style.position = 'absolute';
|
||||
contextMenu.style.left = `${position.x}px`;
|
||||
contextMenu.style.top = `${position.y}px`;
|
||||
contextMenu.style.zIndex = '1000';
|
||||
|
||||
// Menü-Elemente
|
||||
const menuItems = [
|
||||
{ label: 'Gedanken anzeigen', icon: 'fas fa-brain', action: () => this.showThoughtsForNode(node) },
|
||||
{ label: 'Neuen Gedanken erstellen', icon: 'fas fa-plus-circle', action: () => this.createThoughtForNode(node) },
|
||||
{ label: 'Notiz hinzufügen', icon: 'fas fa-sticky-note', action: () => this.addNoteToNode(node) },
|
||||
{ label: 'Knoten bearbeiten', icon: 'fas fa-edit', action: () => this.editNode(node) },
|
||||
{ label: 'Verbindung erstellen', icon: 'fas fa-link', action: () => this.startEdgeCreation(node) },
|
||||
{ label: 'Aus Mindmap entfernen', icon: 'fas fa-trash-alt', action: () => this.removeNodeFromMap(node) }
|
||||
];
|
||||
|
||||
// Menü erstellen
|
||||
menuItems.forEach(item => {
|
||||
const menuItem = document.createElement('div');
|
||||
menuItem.className = 'menu-item';
|
||||
menuItem.innerHTML = `<i class="${item.icon} mr-2"></i> ${item.label}`;
|
||||
menuItem.addEventListener('click', () => {
|
||||
item.action();
|
||||
contextMenu.remove();
|
||||
});
|
||||
contextMenu.appendChild(menuItem);
|
||||
});
|
||||
|
||||
// Anhängen an Body (außerhalb des Cytoscape-Containers)
|
||||
document.body.appendChild(contextMenu);
|
||||
|
||||
// Stellen Sie sicher, dass das Kontextmenü vollständig sichtbar ist
|
||||
const menuRect = contextMenu.getBoundingClientRect();
|
||||
const windowWidth = window.innerWidth;
|
||||
const windowHeight = window.innerHeight;
|
||||
|
||||
if (menuRect.right > windowWidth) {
|
||||
contextMenu.style.left = `${position.x - menuRect.width}px`;
|
||||
}
|
||||
|
||||
if (menuRect.bottom > windowHeight) {
|
||||
contextMenu.style.top = `${position.y - menuRect.height}px`;
|
||||
}
|
||||
}
|
||||
|
||||
// Fügt die Edit-Toolbar zur Mindmap hinzu
|
||||
addEditToolbar() {
|
||||
const toolbar = document.querySelector('.mindmap-toolbar');
|
||||
if (!toolbar) return;
|
||||
|
||||
// Trennlinie
|
||||
const separator = document.createElement('div');
|
||||
separator.className = 'border-l h-6 mx-2 opacity-20';
|
||||
toolbar.appendChild(separator);
|
||||
|
||||
// Bearbeiten-Buttons
|
||||
const editButtons = [
|
||||
{ id: 'add-node-btn', icon: 'fa-plus', text: 'Knoten hinzufügen', action: () => this.showAddNodeDialog() },
|
||||
{ id: 'save-layout-btn', icon: 'fa-save', text: 'Layout speichern', action: () => this.saveCurrentLayout() }
|
||||
];
|
||||
|
||||
editButtons.forEach(btn => {
|
||||
const button = document.createElement('button');
|
||||
button.id = btn.id;
|
||||
button.className = 'mindmap-action-btn edit-btn';
|
||||
button.innerHTML = `<i class="fas ${btn.icon}"></i><span>${btn.text}</span>`;
|
||||
button.addEventListener('click', btn.action);
|
||||
toolbar.appendChild(button);
|
||||
});
|
||||
|
||||
// Animation für die Edit-Buttons
|
||||
const editBtns = document.querySelectorAll('.edit-btn');
|
||||
editBtns.forEach(btn => {
|
||||
btn.style.opacity = '0';
|
||||
btn.style.transform = 'translateY(10px)';
|
||||
|
||||
setTimeout(() => {
|
||||
btn.style.transition = 'all 0.3s ease';
|
||||
btn.style.opacity = '1';
|
||||
btn.style.transform = 'translateY(0)';
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// Zeigt den Dialog zum Hinzufügen eines neuen Knotens
|
||||
showAddNodeDialog(position = null) {
|
||||
// Entferne bestehende Dialoge
|
||||
const existingDialog = document.getElementById('add-node-dialog');
|
||||
if (existingDialog) existingDialog.remove();
|
||||
|
||||
// Erstelle Dialog
|
||||
const dialog = document.createElement('div');
|
||||
dialog.id = 'add-node-dialog';
|
||||
dialog.className = 'fixed inset-0 flex items-center justify-center z-50';
|
||||
dialog.innerHTML = `
|
||||
<div class="fixed inset-0 bg-black bg-opacity-50"></div>
|
||||
<div class="bg-slate-800 rounded-lg p-6 w-full max-w-md relative z-10 border border-purple-500/20">
|
||||
<h3 class="text-xl font-semibold mb-4 text-white">Neuen Knoten hinzufügen</h3>
|
||||
<form id="add-node-form">
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium text-gray-300 mb-1">Name</label>
|
||||
<input type="text" id="node-name" class="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-md text-white">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium text-gray-300 mb-1">Beschreibung</label>
|
||||
<textarea id="node-description" class="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-md text-white resize-none h-24"></textarea>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium text-gray-300 mb-1">Farbe</label>
|
||||
<input type="color" id="node-color" class="w-full h-10 border border-slate-700 rounded-md bg-slate-900" value="#8B5CF6">
|
||||
</div>
|
||||
<div class="flex justify-end gap-3 mt-6">
|
||||
<button type="button" id="cancel-add-node" class="px-4 py-2 bg-slate-700 hover:bg-slate-600 text-white rounded-md transition-colors">Abbrechen</button>
|
||||
<button type="submit" class="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-md transition-colors">Hinzufügen</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Füge Dialog zum Body hinzu
|
||||
document.body.appendChild(dialog);
|
||||
|
||||
// Animation für den Dialog
|
||||
const dialogContent = dialog.querySelector('.bg-slate-800');
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => {
|
||||
dialogContent.style.transition = 'all 0.3s ease';
|
||||
dialogContent.style.opacity = '1';
|
||||
dialogContent.style.transform = 'scale(1)';
|
||||
}, 10);
|
||||
|
||||
// Event-Listener für Abbrechen
|
||||
document.getElementById('cancel-add-node').addEventListener('click', () => {
|
||||
// Animation für das Schließen
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => dialog.remove(), 300);
|
||||
});
|
||||
|
||||
// Event-Listener für Overlay-Klick
|
||||
dialog.querySelector('.fixed.inset-0.bg-black').addEventListener('click', () => {
|
||||
// Animation für das Schließen
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => dialog.remove(), 300);
|
||||
});
|
||||
|
||||
// Event-Listener für Formular
|
||||
document.getElementById('add-node-form').addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const name = document.getElementById('node-name').value;
|
||||
const description = document.getElementById('node-description').value;
|
||||
const color = document.getElementById('node-color').value;
|
||||
|
||||
if (!name.trim()) {
|
||||
this.showFlash('Bitte geben Sie einen Namen für den Knoten ein', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Knoten hinzufügen
|
||||
this.addNodeToMindmap({
|
||||
name,
|
||||
description,
|
||||
color_code: color,
|
||||
position
|
||||
});
|
||||
|
||||
// Dialog schließen
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => dialog.remove(), 300);
|
||||
});
|
||||
|
||||
// Fokus auf das Name-Feld
|
||||
setTimeout(() => document.getElementById('node-name').focus(), 100);
|
||||
}
|
||||
|
||||
// Fügt einen neuen Knoten zur Mindmap hinzu
|
||||
addNodeToMindmap(nodeData) {
|
||||
// API-Anfrage vorbereiten
|
||||
const data = {
|
||||
name: nodeData.name,
|
||||
description: nodeData.description || '',
|
||||
color_code: nodeData.color_code || '#8b5cf6'
|
||||
};
|
||||
|
||||
// Position hinzufügen, falls vorhanden
|
||||
if (nodeData.position) {
|
||||
data.x_position = nodeData.position.x;
|
||||
data.y_position = nodeData.position.y;
|
||||
}
|
||||
|
||||
// API-Anfrage zum Hinzufügen des Knotens
|
||||
fetch('/api/mindmap/public/add_node', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Netzwerkantwort war nicht ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Hinzufügen des neuen Knotens zum Graphen
|
||||
this.cy.add({
|
||||
group: 'nodes',
|
||||
data: {
|
||||
id: `node_${data.node_id}`,
|
||||
name: nodeData.name,
|
||||
description: nodeData.description || '',
|
||||
color: nodeData.color_code
|
||||
},
|
||||
position: nodeData.position || { x: 0, y: 0 }
|
||||
});
|
||||
|
||||
// Flash-Nachricht anzeigen
|
||||
this.showFlash('Knoten erfolgreich hinzugefügt', 'success');
|
||||
|
||||
// Ansicht anpassen
|
||||
this.cy.fit();
|
||||
} else {
|
||||
this.showFlash('Fehler beim Hinzufügen des Knotens: ' + (data.error || 'Unbekannter Fehler'), 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Hinzufügen des Knotens:', error);
|
||||
this.showFlash('Fehler beim Hinzufügen des Knotens', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// Entfernt einen Knoten aus der Mindmap
|
||||
removeNodeFromMap(node) {
|
||||
if (!confirm('Möchten Sie diesen Knoten wirklich aus der Mindmap entfernen?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nodeId = node.id().split('_')[1]; // "node_123" => "123"
|
||||
|
||||
// API-Anfrage zum Entfernen des Knotens
|
||||
fetch(`/api/mindmap/public/remove_node/${nodeId}`, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Netzwerkantwort war nicht ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Knoten aus dem Graphen entfernen
|
||||
this.cy.remove(node);
|
||||
|
||||
// Flash-Nachricht anzeigen
|
||||
this.showFlash('Knoten erfolgreich entfernt', 'success');
|
||||
} else {
|
||||
this.showFlash('Fehler beim Entfernen des Knotens: ' + (data.error || 'Unbekannter Fehler'), 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Entfernen des Knotens:', error);
|
||||
this.showFlash('Fehler beim Entfernen des Knotens', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// Speichert das aktuelle Layout der Mindmap
|
||||
saveCurrentLayout() {
|
||||
// Sammle alle Knotenpositionen
|
||||
const nodePositions = [];
|
||||
this.cy.nodes().forEach(node => {
|
||||
const idParts = node.id().split('_');
|
||||
if (idParts.length === 2 && idParts[0] === 'node') {
|
||||
nodePositions.push({
|
||||
node_id: parseInt(idParts[1]),
|
||||
x_position: node.position('x'),
|
||||
y_position: node.position('y')
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// API-Anfrage zum Speichern des Layouts
|
||||
fetch('/api/mindmap/public/update_layout', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ positions: nodePositions })
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Netzwerkantwort war nicht ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
this.showFlash('Layout erfolgreich gespeichert', 'success');
|
||||
} else {
|
||||
this.showFlash('Fehler beim Speichern des Layouts: ' + (data.error || 'Unbekannter Fehler'), 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Speichern des Layouts:', error);
|
||||
this.showFlash('Fehler beim Speichern des Layouts', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// Zeigt den Dialog zum Bearbeiten eines Knotens
|
||||
editNode(node) {
|
||||
// Entferne bestehende Dialoge
|
||||
const existingDialog = document.getElementById('edit-node-dialog');
|
||||
if (existingDialog) existingDialog.remove();
|
||||
|
||||
// Knotendaten holen
|
||||
const nodeData = node.data();
|
||||
|
||||
// Erstelle Dialog
|
||||
const dialog = document.createElement('div');
|
||||
dialog.id = 'edit-node-dialog';
|
||||
dialog.className = 'fixed inset-0 flex items-center justify-center z-50';
|
||||
dialog.innerHTML = `
|
||||
<div class="fixed inset-0 bg-black bg-opacity-50"></div>
|
||||
<div class="bg-slate-800 rounded-lg p-6 w-full max-w-md relative z-10 border border-purple-500/20">
|
||||
<h3 class="text-xl font-semibold mb-4 text-white">Knoten bearbeiten</h3>
|
||||
<form id="edit-node-form">
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium text-gray-300 mb-1">Name</label>
|
||||
<input type="text" id="node-name" class="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-md text-white" value="${nodeData.name}">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium text-gray-300 mb-1">Beschreibung</label>
|
||||
<textarea id="node-description" class="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-md text-white resize-none h-24">${nodeData.description || ''}</textarea>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="block text-sm font-medium text-gray-300 mb-1">Farbe</label>
|
||||
<input type="color" id="node-color" class="w-full h-10 border border-slate-700 rounded-md bg-slate-900" value="${nodeData.color || '#8B5CF6'}">
|
||||
</div>
|
||||
<div class="flex justify-end gap-3 mt-6">
|
||||
<button type="button" id="cancel-edit-node" class="px-4 py-2 bg-slate-700 hover:bg-slate-600 text-white rounded-md transition-colors">Abbrechen</button>
|
||||
<button type="submit" class="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-md transition-colors">Speichern</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Füge Dialog zum Body hinzu
|
||||
document.body.appendChild(dialog);
|
||||
|
||||
// Animation für den Dialog
|
||||
const dialogContent = dialog.querySelector('.bg-slate-800');
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => {
|
||||
dialogContent.style.transition = 'all 0.3s ease';
|
||||
dialogContent.style.opacity = '1';
|
||||
dialogContent.style.transform = 'scale(1)';
|
||||
}, 10);
|
||||
|
||||
// Event-Listener für Abbrechen
|
||||
document.getElementById('cancel-edit-node').addEventListener('click', () => {
|
||||
// Animation für das Schließen
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => dialog.remove(), 300);
|
||||
});
|
||||
|
||||
// Event-Listener für Overlay-Klick
|
||||
dialog.querySelector('.fixed.inset-0.bg-black').addEventListener('click', () => {
|
||||
// Animation für das Schließen
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => dialog.remove(), 300);
|
||||
});
|
||||
|
||||
// Event-Listener für Formular
|
||||
document.getElementById('edit-node-form').addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const name = document.getElementById('node-name').value;
|
||||
const description = document.getElementById('node-description').value;
|
||||
const color = document.getElementById('node-color').value;
|
||||
|
||||
if (!name.trim()) {
|
||||
this.showFlash('Bitte geben Sie einen Namen für den Knoten ein', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Knoten aktualisieren
|
||||
this.updateNode(node, {
|
||||
name,
|
||||
description,
|
||||
color_code: color
|
||||
});
|
||||
|
||||
// Dialog schließen
|
||||
dialogContent.style.opacity = '0';
|
||||
dialogContent.style.transform = 'scale(0.9)';
|
||||
setTimeout(() => dialog.remove(), 300);
|
||||
});
|
||||
|
||||
// Fokus auf das Name-Feld
|
||||
setTimeout(() => document.getElementById('node-name').focus(), 100);
|
||||
}
|
||||
|
||||
// Aktualisiert einen Knoten in der Mindmap
|
||||
updateNode(node, nodeData) {
|
||||
const nodeId = node.id().split('_')[1]; // "node_123" => "123"
|
||||
|
||||
// API-Anfrage zum Aktualisieren des Knotens
|
||||
fetch(`/api/mindmap/public/update_node/${nodeId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: nodeData.name,
|
||||
description: nodeData.description,
|
||||
color_code: nodeData.color_code
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Netzwerkantwort war nicht ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Aktualisiere Knotendaten im Graph
|
||||
node.data('name', nodeData.name);
|
||||
node.data('description', nodeData.description);
|
||||
node.data('color', nodeData.color_code);
|
||||
|
||||
// Aktualisiere Darstellung
|
||||
this.cy.style()
|
||||
.selector(`#${node.id()}`)
|
||||
.style({
|
||||
'background-color': nodeData.color_code
|
||||
})
|
||||
.update();
|
||||
|
||||
// Flash-Nachricht anzeigen
|
||||
this.showFlash('Knoten erfolgreich aktualisiert', 'success');
|
||||
} else {
|
||||
this.showFlash('Fehler beim Aktualisieren des Knotens: ' + (data.error || 'Unbekannter Fehler'), 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Aktualisieren des Knotens:', error);
|
||||
this.showFlash('Fehler beim Aktualisieren des Knotens', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// Fügt eine Notiz zu einem Knoten hinzu
|
||||
addNoteToNode(node) {
|
||||
// Implementierung für das Hinzufügen von Notizen
|
||||
// Ähnlich wie bei editNode, aber mit anderen Feldern
|
||||
}
|
||||
|
||||
// Startet den Prozess zum Erstellen einer Verbindung
|
||||
startEdgeCreation(node) {
|
||||
// Implementierung für das Erstellen von Verbindungen
|
||||
}
|
||||
|
||||
// ... existing code ...
|
||||
}
|
||||
Reference in New Issue
Block a user