From 3a20ea0282a4f54f117479d025d65565c14eb1e0 Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Sat, 10 May 2025 22:28:19 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20=C3=84nderungen=20commited?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/edit_mindmap.html | 216 +++++++++++++++++++++++++--------- templates/my_account.html | 10 +- templates/user_mindmap.html | 223 ++++++++++++++++++++++++++++++------ 3 files changed, 360 insertions(+), 89 deletions(-) diff --git a/templates/edit_mindmap.html b/templates/edit_mindmap.html index 4211224..4c18072 100644 --- a/templates/edit_mindmap.html +++ b/templates/edit_mindmap.html @@ -231,16 +231,16 @@
-
+
-
-
@@ -253,11 +253,11 @@
- + {# Zurück zur Kontoübersicht geändert #} Zurück - @@ -322,13 +322,60 @@ }); }); - // Formular-Absenden-Animation - const form = document.querySelector('form'); - form.addEventListener('submit', function(e) { - const submitBtn = this.querySelector('.btn-submit'); - submitBtn.innerHTML = ' Wird gespeichert...'; - submitBtn.disabled = true; - }); + // Formular-Absenden-Logik für Metadaten + const editMindmapForm = document.getElementById('edit-mindmap-form'); + const saveDetailsBtn = document.getElementById('save-mindmap-details-btn'); + + if (saveDetailsBtn && editMindmapForm) { + saveDetailsBtn.addEventListener('click', async function(event) { + event.preventDefault(); + + const nameInput = document.getElementById('name'); + const descriptionInput = document.getElementById('description'); + const isPrivateInput = document.getElementById('is_private'); + + const mindmapId = "{{ mindmap.id }}"; // Sicherstellen, dass mindmap.id hier verfügbar ist + const csrfToken = "{{ csrf_token() }}"; + + const data = { + name: nameInput.value, + description: descriptionInput.value, + is_private: isPrivateInput.checked + // Die 'data' (Knoten/Kanten) wird separat vom Cytoscape-Editor gehandhabt + }; + + saveDetailsBtn.innerHTML = ' Wird gespeichert...'; + saveDetailsBtn.disabled = true; + + try { + const response = await fetch(`/api/mindmaps/${mindmapId}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken + }, + body: JSON.stringify(data) + }); + + if (response.ok) { + const result = await response.json(); + showStatus('Metadaten erfolgreich gespeichert!', false); + // Optional: Weiterleitung oder Aktualisierung der Seiteninhalte + // window.location.href = "{{ url_for('my_account') }}"; + } else { + const errorData = await response.json(); + console.error('Fehler beim Speichern der Metadaten:', errorData); + showStatus(`Fehler: ${errorData.error || response.statusText}`, true); + } + } catch (error) { + console.error('Netzwerkfehler oder anderer Fehler:', error); + showStatus('Speichern fehlgeschlagen. Netzwerkproblem?', true); + } finally { + saveDetailsBtn.innerHTML = ' Änderungen speichern'; + saveDetailsBtn.disabled = false; + } + }); + } // Mindmap initialisieren const mindmap = new MindMap.Visualization('cy', { @@ -337,56 +384,116 @@ onNodeClick: function(nodeData) { console.log("Knoten ausgewählt:", nodeData); }, - onChange: function(data) { - // Automatisches Speichern bei Änderungen - fetch('/api/mindmap/{{ mindmap.id }}/update', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': '{{ csrf_token() }}' - }, - body: JSON.stringify(data) - }).then(response => { - if (!response.ok) { - throw new Error('Netzwerkfehler beim Speichern'); - } - console.log('Änderungen gespeichert'); - }).catch(error => { - console.error('Fehler beim Speichern:', error); - alert('Fehler beim Speichern der Änderungen'); - }); + onChange: function(dataFromCytoscape) { + // Automatisches Speichern bei Änderungen der Mindmap-Struktur + // Die Metadaten (Name, Beschreibung, is_private) werden separat über das Formular oben gespeichert. + // Diese onChange Funktion kümmert sich nur um die Strukturdaten (Knoten/Kanten). + const mindmapId = "{{ mindmap.id }}"; + const csrfToken = "{{ csrf_token() }}"; + + // Debounce-Funktion, um API-Aufrufe zu limitieren + let debounceTimer; + const debounceSaveStructure = (currentMindmapData) => { + clearTimeout(debounceTimer); + debounceTimer = setTimeout(() => { + // Der Backend-Endpunkt PUT /api/mindmaps/ erwartet ein Objekt, + // das die zu aktualisierenden Felder enthält. Für die Struktur ist das 'data'. + const payload = { + data: currentMindmapData // Dies sind die von Cytoscape gelieferten Strukturdaten + }; + + // showStatus('Speichere Struktur...', false); // Status wird jetzt über Event gehandhabt + fetch(`/api/mindmaps/${mindmapId}`, { // Endpunkt angepasst + method: 'PUT', // Methode zu PUT geändert + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken + }, + body: JSON.stringify(payload) // Sende die Mindmap-Daten als { data: ... } + }).then(response => { + if (!response.ok) { + response.json().then(err => { + console.error('Fehler beim Speichern der Struktur:', err); + document.dispatchEvent(new CustomEvent('mindmapError', { detail: { message: `Struktur: ${err.message || err.error || 'Speicherfehler'}` } })); + }).catch(() => { + console.error('Fehler beim Speichern der Struktur, Status:', response.statusText); + document.dispatchEvent(new CustomEvent('mindmapError', { detail: { message: `Struktur: ${response.statusText}` } })); + }); + // throw new Error('Netzwerkfehler beim Speichern der Struktur'); // Wird schon behandelt + return; // Verhindere weitere Verarbeitung bei Fehler + } + return response.json(); + }).then(responseData => { + if (responseData) { // Nur wenn response.ok war + console.log('Mindmap-Struktur erfolgreich gespeichert:', responseData); + // Die responseData von einem PUT könnte die aktualisierte Mindmap oder nur eine Erfolgsmeldung sein. + // Annahme: { message: "Mindmap updated successfully", mindmap: { ... } } oder ähnlich + document.dispatchEvent(new CustomEvent('mindmapSaved', { detail: { message: 'Struktur aktualisiert!' }})); + } + }).catch(error => { + console.error('Netzwerkfehler oder anderer Fehler beim Speichern der Struktur:', error); + // Vermeide doppelte Fehlermeldung, falls schon durch !response.ok behandelt + if (!document.querySelector('.bg-red-500')) { // Prüft, ob schon eine Fehlermeldung angezeigt wird + document.dispatchEvent(new CustomEvent('mindmapError', { detail: { message: 'Struktur: Netzwerkfehler' } })); + } + }); + }, 1500); // Speichern 1.5 Sekunden nach der letzten Änderung + }; + + debounceSaveStructure(dataFromCytoscape); // Aufruf der Debounce-Funktion mit Cytoscape-Daten } }); - // Formularfelder mit Mindmap verbinden - const nameInput = document.getElementById('name'); - const descriptionInput = document.getElementById('description'); - - // Aktualisiere Mindmap wenn sich die Eingaben ändern - nameInput.addEventListener('input', function() { - if (mindmap.cy) { - const rootNode = mindmap.cy.$('#root'); - if (rootNode.length > 0) { - rootNode.data('name', this.value || 'Mindmap'); - mindmap.saveToServer(); - } - } - }); + // Die Verknüpfung der Formularfelder (Name, Beschreibung) mit dem Cytoscape Root-Knoten wird entfernt, + // da die Metadaten nun über das separate Formular oben gespeichert werden und nicht mehr direkt + // die Cytoscape-Daten manipulieren sollen. Die Logik für mindmap.saveToServer() wurde entfernt, + // da das Speichern jetzt über den onChange Handler mit PUT /api/mindmaps/ erfolgt. + // const nameInput = document.getElementById('name'); // Bereits oben deklariert für Metadaten + // nameInput.removeEventListener('input', ...); // Event Listener muss hier nicht entfernt werden, da er nicht neu hinzugefügt wird. // Initialisiere die Mindmap mit existierenden Daten mindmap.initialize().then(() => { console.log("Mindmap-Editor initialisiert"); + const mindmapId = "{{ mindmap.id }}"; + const csrfToken = "{{ csrf_token() }}"; - // Lade existierende Daten - fetch('/api/mindmap/{{ mindmap.id }}/data') - .then(response => response.json()) - .then(data => { - mindmap.loadData(data); - console.log("Mindmap-Daten geladen"); + // Lade existierende Daten für die Mindmap-Struktur + fetch(`/api/mindmaps/${mindmapId}`, { // Endpunkt für GET angepasst + method: 'GET', + headers: { + 'Accept': 'application/json', + 'X-CSRFToken': csrfToken + } + }) + .then(response => { + if (!response.ok) { + response.json().then(err => { + showStatus(`Fehler beim Laden: ${err.message || err.error || response.statusText}`, true); + }).catch(() => { + showStatus(`Fehler beim Laden: ${response.statusText}`, true); + }); + throw new Error(`Netzwerkantwort war nicht ok: ${response.statusText}`); + } + return response.json(); + }) + .then(mindmapDataFromServer => { + // Die API GET /api/mindmaps/ gibt ein Objekt zurück, das { id, name, description, is_private, data, ... } enthält. + // Wir brauchen nur den 'data'-Teil (Struktur) für Cytoscape. + // Die Metadaten (name, description, is_private) werden bereits serverseitig in die Formularfelder gerendert. + if (mindmapDataFromServer && mindmapDataFromServer.data) { + mindmap.loadData(mindmapDataFromServer.data); // Lade nur die Strukturdaten + console.log("Mindmap-Strukturdaten geladen:", mindmapDataFromServer.data); + showStatus("Mindmap geladen.", false); + } else { + console.error("Fehler: Mindmap-Daten (Struktur) nicht im erwarteten Format:", mindmapDataFromServer); + showStatus("Fehler: Mindmap-Struktur konnte nicht geladen werden (Formatfehler).", true); + } }) .catch(error => { - console.error("Fehler beim Laden der Mindmap-Daten:", error); - alert("Fehler beim Laden der Mindmap"); + console.error("Fehler beim Laden der Mindmap-Strukturdaten:", error); + if (!document.querySelector('.bg-red-500')) { // Prüft, ob schon eine Fehlermeldung angezeigt wird + showStatus("Laden der Struktur fehlgeschlagen.", true); + } }); }).catch(error => { console.error("Fehler bei der Initialisierung des Editors:", error); @@ -411,8 +518,9 @@ } // Event-Listener für Speicherstatus - document.addEventListener('mindmapSaved', () => { - showStatus('Änderungen gespeichert'); + document.addEventListener('mindmapSaved', (event) => { + const message = event.detail && event.detail.message ? event.detail.message : 'Erfolgreich gespeichert!'; + showStatus(message, false); }); document.addEventListener('mindmapError', (event) => { diff --git a/templates/my_account.html b/templates/my_account.html index fce6524..b68598e 100644 --- a/templates/my_account.html +++ b/templates/my_account.html @@ -353,22 +353,26 @@ } try { + const csrfToken = "{{ csrf_token() }}"; // CSRF Token holen const response = await fetch('/api/mindmaps', { method: 'POST', headers: { 'Content-Type': 'application/json', + 'X-CSRFToken': csrfToken // CSRF Token im Header senden }, - body: JSON.stringify({ name, description }), + body: JSON.stringify({ name, description, is_private: false }), // is_private standardmäßig auf false setzen }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || `HTTP error! status: ${response.status}`); } const newMindmap = await response.json(); - showNotification(`Mindmap "${newMindmap.name}" erfolgreich erstellt.`, 'success'); + showNotification(`Mindmap "${newMindmap.name}" erfolgreich erstellt. Weiterleitung...`, 'success'); createMindmapModal.classList.add('hidden'); createMindmapForm.reset(); - fetchUserMindmaps(); // Liste aktualisieren + // fetchUserMindmaps(); // Liste wird auf der neuen Seite ohnehin neu geladen oder ist nicht direkt sichtbar. + // Weiterleitung zur Bearbeitungsseite der neuen Mindmap + window.location.href = `/edit_mindmap/${newMindmap.id}`; } catch (error) { console.error('Fehler beim Erstellen der Mindmap:', error); showNotification(`Fehler beim Erstellen: ${error.message}`, 'error'); diff --git a/templates/user_mindmap.html b/templates/user_mindmap.html index 02293d4..7937d55 100644 --- a/templates/user_mindmap.html +++ b/templates/user_mindmap.html @@ -324,7 +324,7 @@
-
+
@@ -353,39 +353,198 @@ -{% endblock %} \ No newline at end of file +{% endblock %} \ No newline at end of file