chore: Änderungen commited
This commit is contained in:
@@ -324,7 +324,7 @@
|
||||
<!-- Mindmap Container mit Positionsindikator -->
|
||||
<div class="relative rounded-xl overflow-hidden border transition-all duration-300"
|
||||
x-bind:class="darkMode ? 'border-gray-700/50' : 'border-gray-300/50'">
|
||||
<div id="cy"></div>
|
||||
<div id="cy" data-mindmap-id="{{ mindmap.id }}"></div>
|
||||
|
||||
<!-- Informationsanzeige für ausgewählten Knoten -->
|
||||
<div id="node-info-panel" class="node-info-panel p-4">
|
||||
@@ -353,39 +353,198 @@
|
||||
<script src="{{ url_for('static', filename='js/cytoscape.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/mindmap-init.js') }}"></script>
|
||||
<script nonce="{{ csp_nonce }}">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Benutzer-Mindmap-ID für die API-Anfragen
|
||||
const mindmapId = {{ mindmap.id }};
|
||||
|
||||
// Erstellt eine neue MindMap-Instanz für die Benutzer-Mindmap
|
||||
window.userMindmap = new MindMap('#cy', {
|
||||
editable: true,
|
||||
isUserLoggedIn: true,
|
||||
isPublicMap: false,
|
||||
userMindmapId: mindmapId,
|
||||
fitViewOnInit: true,
|
||||
callbacks: {
|
||||
onLoad: function() {
|
||||
console.log('Benutzerdefinierte Mindmap wurde geladen');
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
const cyContainer = document.getElementById('cy');
|
||||
if (!cyContainer) {
|
||||
console.error("Mindmap container #cy not found!");
|
||||
return;
|
||||
}
|
||||
const mindmapId = cyContainer.dataset.mindmapId;
|
||||
const nodeInfoPanel = document.getElementById('node-info-panel');
|
||||
const nodeDescription = document.getElementById('node-description');
|
||||
const connectedNodesContainer = document.getElementById('connected-nodes');
|
||||
const mindmapNameH1 = document.querySelector('h1.gradient-text');
|
||||
const mindmapDescriptionP = document.querySelector('p.opacity-80.mt-1');
|
||||
|
||||
// Funktion zum Anzeigen von Benachrichtigungen (vereinfacht)
|
||||
function showUINotification(message, type = 'success') {
|
||||
const notificationArea = document.getElementById('notification-area-usr') || createUINotificationArea();
|
||||
const notificationId = `notif-usr-${Date.now()}`;
|
||||
const bgColor = type === 'success' ? 'bg-green-500' : (type === 'error' ? 'bg-red-500' : 'bg-blue-500');
|
||||
|
||||
const notificationElement = `
|
||||
<div id="${notificationId}" class="p-3 mb-3 text-sm text-white rounded-lg ${bgColor} animate-fadeIn" role="alert">
|
||||
<span>${message}</span>
|
||||
</div>
|
||||
`;
|
||||
notificationArea.insertAdjacentHTML('beforeend', notificationElement);
|
||||
|
||||
setTimeout(() => {
|
||||
const el = document.getElementById(notificationId);
|
||||
if (el) {
|
||||
el.classList.add('animate-fadeOut');
|
||||
setTimeout(() => el.remove(), 500);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function createUINotificationArea() {
|
||||
const area = document.createElement('div');
|
||||
area.id = 'notification-area-usr';
|
||||
area.className = 'fixed top-20 right-5 z-[1001] w-auto max-w-xs'; // höhere z-index
|
||||
document.body.appendChild(area);
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.animate-fadeIn { animation: fadeIn 0.3s ease-out; }
|
||||
.animate-fadeOut { animation: fadeOut 0.3s ease-in forwards; }
|
||||
@keyframes fadeIn { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
|
||||
@keyframes fadeOut { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(20px); } }
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
return area;
|
||||
}
|
||||
|
||||
async function fetchMindmapData(id) {
|
||||
try {
|
||||
const response = await fetch(`/api/mindmaps/${id}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Mindmap-Daten:', error);
|
||||
showUINotification('Fehler beim Laden der Mindmap-Daten.', 'error');
|
||||
cyContainer.innerHTML = '<p class="text-center text-red-500 p-10">Konnte Mindmap nicht laden.</p>';
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Event-Listener für Notiz-Button
|
||||
document.getElementById('add-note-btn').addEventListener('click', function() {
|
||||
// Erstellt eine neue Notiz in der Mitte des Viewports
|
||||
const position = window.userMindmap.cy.pan();
|
||||
}
|
||||
|
||||
const mindmapData = await fetchMindmapData(mindmapId);
|
||||
|
||||
if (mindmapData) {
|
||||
if(mindmapNameH1) mindmapNameH1.textContent = mindmapData.name;
|
||||
if(mindmapDescriptionP) mindmapDescriptionP.textContent = mindmapData.description || "Keine Beschreibung vorhanden.";
|
||||
|
||||
window.userMindmap.showAddNoteDialog({
|
||||
x: position.x,
|
||||
y: position.y
|
||||
// Cytoscape initialisieren
|
||||
const cy = cytoscape({
|
||||
container: cyContainer,
|
||||
elements: mindmapData.elements || [], // Verwende 'elements' aus der API-Antwort
|
||||
style: [
|
||||
{
|
||||
selector: 'node',
|
||||
style: {
|
||||
'background-color': 'data(color)',
|
||||
'label': 'data(label)',
|
||||
'color': 'data(fontColor)',
|
||||
'text-valign': 'center',
|
||||
'text-halign': 'center',
|
||||
'font-size': 'data(fontSize)',
|
||||
'width': ele => ele.data('isCenter') ? 60 : (ele.data('size') || 40),
|
||||
'height': ele => ele.data('isCenter') ? 60 : (ele.data('size') || 40),
|
||||
'border-width': 2,
|
||||
'border-color': '#fff',
|
||||
'shape': 'ellipse',
|
||||
'text-outline-color': '#555',
|
||||
'text-outline-width': 1,
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: 'edge',
|
||||
style: {
|
||||
'width': ele => ele.data('strength') ? ele.data('strength') * 1.5 : 2,
|
||||
'line-color': ele => ele.data('color') || '#9dbaea',
|
||||
'target-arrow-color': ele => ele.data('color') || '#9dbaea',
|
||||
'target-arrow-shape': 'triangle',
|
||||
'curve-style': 'bezier'
|
||||
}
|
||||
},
|
||||
{
|
||||
selector: 'node:selected',
|
||||
style: {
|
||||
'border-color': '#f59e42',
|
||||
'border-width': 3,
|
||||
}
|
||||
}
|
||||
],
|
||||
layout: {
|
||||
name: 'cose',
|
||||
idealEdgeLength: 100,
|
||||
nodeOverlap: 20,
|
||||
refresh: 20,
|
||||
fit: true,
|
||||
padding: 30,
|
||||
randomize: false,
|
||||
componentSpacing: 100,
|
||||
nodeRepulsion: 400000,
|
||||
edgeElasticity: 100,
|
||||
nestingFactor: 5,
|
||||
gravity: 80,
|
||||
numIter: 1000,
|
||||
initialTemp: 200,
|
||||
coolingFactor: 0.95,
|
||||
minTemp: 1.0
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Event-Listener für Layout-Speichern-Button
|
||||
document.getElementById('save-layout-btn').addEventListener('click', function() {
|
||||
window.userMindmap.saveLayout();
|
||||
});
|
||||
});
|
||||
window.cyInstance = cy; // Für globalen Zugriff falls nötig
|
||||
|
||||
cy.on('tap', 'node', function(evt){
|
||||
const node = evt.target;
|
||||
if (nodeDescription) nodeDescription.textContent = node.data('description') || 'Keine Beschreibung für diesen Knoten.';
|
||||
|
||||
if (connectedNodesContainer) {
|
||||
connectedNodesContainer.innerHTML = '';
|
||||
const connected = node.connectedEdges().otherNodes();
|
||||
if (connected.length > 0) {
|
||||
connected.forEach(cn => {
|
||||
const link = document.createElement('span');
|
||||
link.className = 'node-link';
|
||||
link.textContent = cn.data('label');
|
||||
link.style.backgroundColor = cn.data('color') || '#60a5fa';
|
||||
link.addEventListener('click', () => {
|
||||
cy.center(cn);
|
||||
cn.select();
|
||||
// Info Panel für den geklickten verbundenen Knoten aktualisieren
|
||||
if (nodeDescription) nodeDescription.textContent = cn.data('description') || 'Keine Beschreibung für diesen Knoten.';
|
||||
// Rekursiv verbundene Knoten des neu ausgewählten Knotens anzeigen (optional)
|
||||
});
|
||||
connectedNodesContainer.appendChild(link);
|
||||
});
|
||||
} else {
|
||||
connectedNodesContainer.innerHTML = '<p class="opacity-70 text-sm">Keine direkten Verbindungen.</p>';
|
||||
}
|
||||
}
|
||||
if (nodeInfoPanel) nodeInfoPanel.classList.add('visible');
|
||||
});
|
||||
|
||||
cy.on('tap', function(evt){
|
||||
if(evt.target === cy){ // Klick auf Hintergrund
|
||||
if (nodeInfoPanel) nodeInfoPanel.classList.remove('visible');
|
||||
}
|
||||
});
|
||||
|
||||
// Toolbar-Buttons
|
||||
document.getElementById('fit-btn')?.addEventListener('click', () => cy.fit(null, 50));
|
||||
document.getElementById('reset-btn')?.addEventListener('click', () => cy.layout({name: 'cose', animate:true}).run());
|
||||
|
||||
let labelsVisible = true;
|
||||
document.getElementById('toggle-labels-btn')?.addEventListener('click', () => {
|
||||
labelsVisible = !labelsVisible;
|
||||
cy.style().selector('node').style({'text-opacity': labelsVisible ? 1 : 0}).update();
|
||||
});
|
||||
|
||||
// TODO: add-note-btn und save-layout-btn Funktionalität (benötigt /edit_mindmap Seite oder API Endpunkte)
|
||||
document.getElementById('add-note-btn').addEventListener('click', function() {
|
||||
showUINotification('Notizfunktion wird auf der Bearbeitungsseite implementiert.', 'info');
|
||||
});
|
||||
document.getElementById('save-layout-btn').addEventListener('click', function() {
|
||||
showUINotification('Layout-Speicherung wird auf der Bearbeitungsseite implementiert.', 'info');
|
||||
});
|
||||
|
||||
} else {
|
||||
// Fallback, falls mindmapData null ist
|
||||
if(mindmapNameH1) mindmapNameH1.textContent = "Mindmap nicht gefunden";
|
||||
cyContainer.innerHTML = '<p class="text-center text-red-500 p-10">Die angeforderte Mindmap konnte nicht geladen werden.</p>';
|
||||
}
|
||||
}); // End of DOMContentLoaded
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user