Update app.py and COMMON_ERRORS.md for improved clarity and functionality: Correct the comment in app.py from "Kontext-Prozessor" to "Context-Prozessor" for better understanding. Enhance COMMON_ERRORS.md by adding new common errors and solutions related to TypeScript usage, OAuth implementation, and neural network background animation issues. Update mindmap page scripts to ensure proper global availability of functions and improve error handling for user notifications. Adjust template references for Tailwind CSS and Alpine.js to support both CDN and local versions, ensuring better resource loading and compatibility.
This commit is contained in:
109
COMMON_ERRORS.md
109
COMMON_ERRORS.md
@@ -3,12 +3,17 @@
|
|||||||
- Implementierung von Content Security Policy (CSP) - UNTER KEINEN UMSTÄNDEN!
|
- Implementierung von Content Security Policy (CSP) - UNTER KEINEN UMSTÄNDEN!
|
||||||
- Implementierung von Cross-Site Request Forgery (CSRF) Schutz
|
- Implementierung von Cross-Site Request Forgery (CSRF) Schutz
|
||||||
- Implementierung von Security Headers
|
- Implementierung von Security Headers
|
||||||
|
- Verwendung von TypeScript anstelle von JavaScript
|
||||||
|
- Implementierung von OAuth oder anderen externen Authentifizierungsmethoden
|
||||||
|
|
||||||
# HÄUFIGE FEHLER:
|
# HÄUFIGE FEHLER:
|
||||||
- Verwendung der falschen Datenbank (die korrekte ist: database/systades.db)
|
- Verwendung der falschen Datenbank (die korrekte ist: database/systades.db)
|
||||||
- Falsche Pfadangaben bei statischen Dateien
|
- Falsche Pfadangaben bei statischen Dateien
|
||||||
- Vergessen der deutschen Spracheinstellungen in Templates
|
- Vergessen der deutschen Spracheinstellungen in Templates
|
||||||
- Nicht beachten der vorhandenen Projektstruktur
|
- Nicht beachten der vorhandenen Projektstruktur
|
||||||
|
- Falsche Einbindung der Neural Network Background Animation
|
||||||
|
- Verwendung von englischen Variablennamen in deutschen Funktionen
|
||||||
|
- Vergessen der Mindmap-Datenstruktur gemäß der Roadmap
|
||||||
|
|
||||||
# Häufige Fehler und Lösungen
|
# Häufige Fehler und Lösungen
|
||||||
|
|
||||||
@@ -29,6 +34,35 @@
|
|||||||
```html
|
```html
|
||||||
<link href="{{ url_for('static', filename='css/tailwind.min.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='css/tailwind.min.css') }}" rel="stylesheet">
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Problem: CSP-Fehler (script-src-elem 'none', font-src 'none', etc.)
|
||||||
|
**Fehler:** Skripte werden aufgrund von CSP-Einschränkungen blockiert.
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
1. WICHTIG: CSP-Einschränkungen NICHT implementieren! Diese sind im Projekt unerwünscht.
|
||||||
|
|
||||||
|
2. Falls CSP-Header bereits vorhanden sind, entfernen Sie diese aus der Anwendung:
|
||||||
|
```python
|
||||||
|
# Entfernen Sie diesen Code, falls vorhanden:
|
||||||
|
# @app.after_request
|
||||||
|
# def add_security_headers(response):
|
||||||
|
# response.headers['Content-Security-Policy'] = '...'
|
||||||
|
# return response
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Stellen Sie sicher, dass externe Ressourcen direkt geladen werden:
|
||||||
|
```html
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/alpine.min.js') }}" defer></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Für Inline-Skripte keine Nonce verwenden:
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
// Inline-JavaScript-Code ohne Einschränkungen
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
### Problem: Tailwind CSS CDN wird blockiert
|
### Problem: Tailwind CSS CDN wird blockiert
|
||||||
**Fehler:** Tailwind CSS kann nicht von CDN geladen werden.
|
**Fehler:** Tailwind CSS kann nicht von CDN geladen werden.
|
||||||
|
|
||||||
@@ -62,3 +96,78 @@
|
|||||||
**Lösung:**
|
**Lösung:**
|
||||||
1. Standard-Admin-Benutzer erstellen: `python TOOLS.py user:admin`
|
1. Standard-Admin-Benutzer erstellen: `python TOOLS.py user:admin`
|
||||||
2. Passwort zurücksetzen: `python TOOLS.py user:reset-pw -u USERNAME -p NEWPASSWORD`
|
2. Passwort zurücksetzen: `python TOOLS.py user:reset-pw -u USERNAME -p NEWPASSWORD`
|
||||||
|
|
||||||
|
## Neural Network Background
|
||||||
|
|
||||||
|
### Problem: Hintergrund-Animation wird nicht angezeigt
|
||||||
|
**Fehler:** Die Neural Network Animation im Hintergrund erscheint nicht.
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
1. Überprüfen Sie, ob die Datei `static/neural-network-background.js` korrekt eingebunden ist:
|
||||||
|
```html
|
||||||
|
<script src="{{ url_for('static', filename='neural-network-background.js') }}"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Initialisieren Sie die Animation im Template:
|
||||||
|
```html
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const background = new NeuralNetworkBackground();
|
||||||
|
background.initialize();
|
||||||
|
background.animate();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Stellen Sie sicher, dass keine CSS-Regeln die Animation überdecken:
|
||||||
|
```css
|
||||||
|
#neural-network-background {
|
||||||
|
z-index: -10;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mindmap-Funktionalität
|
||||||
|
|
||||||
|
### Problem: Mindmap-Daten werden nicht geladen
|
||||||
|
**Fehler:** Die dynamische Mindmap zeigt keine Daten an.
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
1. Überprüfen Sie die API-Endpunkte für die Mindmap-Daten:
|
||||||
|
```python
|
||||||
|
@app.route('/api/mindmap/nodes', methods=['GET'])
|
||||||
|
def get_mindmap_nodes():
|
||||||
|
# Implementierung...
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Stellen Sie sicher, dass die AJAX-Anfragen korrekt implementiert sind:
|
||||||
|
```javascript
|
||||||
|
fetch('/api/mindmap/nodes')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
// Verarbeitung der Mindmap-Daten
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Überprüfen Sie die Datenbankeinträge für Mindmap-Knoten und -Verbindungen.
|
||||||
|
|
||||||
|
## ChatGPT-Assistent
|
||||||
|
|
||||||
|
### Problem: Assistent reagiert nicht auf Eingaben
|
||||||
|
**Fehler:** Der ChatGPT-Assistent verarbeitet keine Benutzereingaben.
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
1. Überprüfen Sie die Einbindung der JavaScript-Datei:
|
||||||
|
```html
|
||||||
|
<script src="{{ url_for('static', filename='js/modules/chatgpt-assistant.js') }}"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Stellen Sie sicher, dass der Assistent korrekt initialisiert wird:
|
||||||
|
```javascript
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const assistant = new ChatGPTAssistant();
|
||||||
|
assistant.initialize();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Überprüfen Sie die API-Endpunkte für die Kommunikation mit dem Assistenten.
|
||||||
Binary file not shown.
2
app.py
2
app.py
@@ -73,7 +73,7 @@ def inject_globals():
|
|||||||
'current_year': datetime.now().year
|
'current_year': datetime.now().year
|
||||||
}
|
}
|
||||||
|
|
||||||
# Kontext-Prozessor für alle Templates
|
# Context-Prozessor für alle Templates
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_current_year():
|
def inject_current_year():
|
||||||
return {'current_year': datetime.now().year}
|
return {'current_year': datetime.now().year}
|
||||||
|
|||||||
18
static/css/tailwind.min.css
vendored
18
static/css/tailwind.min.css
vendored
@@ -1,16 +1,6 @@
|
|||||||
/*
|
/**
|
||||||
* Tailwind CSS v3.4.16
|
* Failed to bundle using Rollup v2.79.2: the file imports a not supported node.js built-in module "fs".
|
||||||
*
|
* If you believe this to be an issue with jsDelivr, and not with the package itself, please open an issue at https://github.com/jsdelivr/jsdelivr
|
||||||
* This is a placeholder file. For production, you should:
|
|
||||||
* 1. Install Tailwind CSS as a PostCSS plugin: https://tailwindcss.com/docs/installation
|
|
||||||
* 2. Run the Tailwind CLI to compile this file with your custom configuration
|
|
||||||
* 3. Replace this file with the compiled CSS
|
|
||||||
*
|
|
||||||
* The actual file should be generated using:
|
|
||||||
* npx tailwindcss -i ./src/input.css -o ./static/css/tailwind.min.css --minify
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Base Tailwind imports */
|
throw new Error('Failed to bundle using Rollup v2.79.2: the file imports a not supported node.js built-in module "fs". If you believe this to be an issue with jsDelivr, and not with the package itself, please open an issue at https://github.com/jsdelivr/jsdelivr');
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
15
static/js/alpine.min.js
vendored
15
static/js/alpine.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -2,9 +2,6 @@
|
|||||||
* MindMap - Hauptdatei für globale JavaScript-Funktionen
|
* MindMap - Hauptdatei für globale JavaScript-Funktionen
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Import des ChatGPT-Assistenten
|
|
||||||
import ChatGPTAssistant from './modules/chatgpt-assistant.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hauptmodul für die MindMap-Anwendung
|
* Hauptmodul für die MindMap-Anwendung
|
||||||
* Verwaltet die globale Anwendungslogik
|
* Verwaltet die globale Anwendungslogik
|
||||||
@@ -38,10 +35,12 @@ const MindMap = {
|
|||||||
console.log('MindMap-Anwendung wird initialisiert...');
|
console.log('MindMap-Anwendung wird initialisiert...');
|
||||||
|
|
||||||
// Initialisiere den ChatGPT-Assistenten
|
// Initialisiere den ChatGPT-Assistenten
|
||||||
const assistant = new ChatGPTAssistant();
|
if (typeof ChatGPTAssistant !== 'undefined') {
|
||||||
assistant.init();
|
const assistant = new ChatGPTAssistant();
|
||||||
// Speichere als Teil von MindMap
|
assistant.init();
|
||||||
this.assistant = assistant;
|
// Speichere als Teil von MindMap
|
||||||
|
this.assistant = assistant;
|
||||||
|
}
|
||||||
|
|
||||||
// Seiten-spezifische Initialisierer aufrufen
|
// Seiten-spezifische Initialisierer aufrufen
|
||||||
if (this.currentPage && this.pageInitializers[this.currentPage]) {
|
if (this.currentPage && this.pageInitializers[this.currentPage]) {
|
||||||
@@ -74,6 +73,12 @@ const MindMap = {
|
|||||||
try {
|
try {
|
||||||
console.log('Initialisiere Mindmap...');
|
console.log('Initialisiere Mindmap...');
|
||||||
|
|
||||||
|
// Prüfe, ob MindMapVisualization geladen ist
|
||||||
|
if (typeof MindMapVisualization === 'undefined') {
|
||||||
|
console.error('MindMapVisualization-Klasse ist nicht definiert!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialisiere die Mindmap
|
// Initialisiere die Mindmap
|
||||||
const mindmap = new MindMapVisualization('#mindmap-container', {
|
const mindmap = new MindMapVisualization('#mindmap-container', {
|
||||||
height: mindmapContainer.clientHeight || 600,
|
height: mindmapContainer.clientHeight || 600,
|
||||||
@@ -227,6 +232,3 @@ const MindMap = {
|
|||||||
|
|
||||||
// Globale Export für andere Module
|
// Globale Export für andere Module
|
||||||
window.MindMap = MindMap;
|
window.MindMap = MindMap;
|
||||||
|
|
||||||
// Export als Modul
|
|
||||||
export default MindMap;
|
|
||||||
@@ -568,5 +568,5 @@ class ChatGPTAssistant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exportiere die Klasse für die Verwendung in anderen Modulen
|
// Mache die Klasse global verfügbar
|
||||||
export default ChatGPTAssistant;
|
window.ChatGPTAssistant = ChatGPTAssistant;
|
||||||
@@ -3,12 +3,18 @@
|
|||||||
* Spezifische Funktionen für die Mindmap-Seite
|
* Spezifische Funktionen für die Mindmap-Seite
|
||||||
*/
|
*/
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
// Füge das Modul zum globalen MindMap-Objekt hinzu
|
||||||
// Registriere den Initialisierer im MindMap-Objekt
|
if (!window.MindMap) {
|
||||||
if (window.MindMap) {
|
window.MindMap = {};
|
||||||
window.MindMap.pageInitializers.mindmap = initMindmapPage;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// Registriere den Initialisierer im MindMap-Objekt
|
||||||
|
if (window.MindMap) {
|
||||||
|
window.MindMap.pageInitializers = window.MindMap.pageInitializers || {};
|
||||||
|
window.MindMap.pageInitializers.mindmap = initMindmapPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Prüfe, ob wir auf der Mindmap-Seite sind und initialisiere
|
// Prüfe, ob wir auf der Mindmap-Seite sind und initialisiere
|
||||||
if (document.body.dataset.page === 'mindmap') {
|
if (document.body.dataset.page === 'mindmap') {
|
||||||
initMindmapPage();
|
initMindmapPage();
|
||||||
@@ -461,13 +467,13 @@ function initMindmapPage() {
|
|||||||
|
|
||||||
// Erfolgsbenachrichtigung
|
// Erfolgsbenachrichtigung
|
||||||
if (window.MindMap && window.MindMap.showNotification) {
|
if (window.MindMap && window.MindMap.showNotification) {
|
||||||
MindMap.showNotification('Gedanke erfolgreich gespeichert.', 'success');
|
window.MindMap.showNotification('Gedanke erfolgreich gespeichert.', 'success');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Fehler beim Speichern:', error);
|
console.error('Fehler beim Speichern:', error);
|
||||||
if (window.MindMap && window.MindMap.showNotification) {
|
if (window.MindMap && window.MindMap.showNotification) {
|
||||||
MindMap.showNotification('Fehler beim Speichern des Gedankens.', 'error');
|
window.MindMap.showNotification('Fehler beim Speichern des Gedankens.', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -483,7 +489,7 @@ function initMindmapPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zeigt die Kommentare zu einem Gedanken an
|
* Füge globale Funktionen für das Mindmap-Objekt hinzu
|
||||||
*/
|
*/
|
||||||
window.showComments = async function(thoughtId) {
|
window.showComments = async function(thoughtId) {
|
||||||
try {
|
try {
|
||||||
@@ -505,7 +511,11 @@ window.showComments = async function(thoughtId) {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Fehler beim Laden der Kommentare:', error);
|
console.error('Fehler beim Laden der Kommentare:', error);
|
||||||
MindMap.showNotification('Fehler beim Laden der Kommentare.', 'error');
|
if (window.MindMap && window.MindMap.showNotification) {
|
||||||
|
window.MindMap.showNotification('Fehler beim Laden der Kommentare.', 'error');
|
||||||
|
} else {
|
||||||
|
alert('Fehler beim Laden der Kommentare.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -532,7 +542,11 @@ window.showRelations = async function(thoughtId) {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Fehler beim Laden der Beziehungen:', error);
|
console.error('Fehler beim Laden der Beziehungen:', error);
|
||||||
MindMap.showNotification('Fehler beim Laden der Beziehungen.', 'error');
|
if (window.MindMap && window.MindMap.showNotification) {
|
||||||
|
window.MindMap.showNotification('Fehler beim Laden der Beziehungen.', 'error');
|
||||||
|
} else {
|
||||||
|
alert('Fehler beim Laden der Beziehungen.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,11 @@
|
|||||||
<meta name="keywords" content="systades, wissen, visualisierung, lernen, gedanken, theorie">
|
<meta name="keywords" content="systades, wissen, visualisierung, lernen, gedanken, theorie">
|
||||||
<meta name="author" content="Systades-Team">
|
<meta name="author" content="Systades-Team">
|
||||||
|
|
||||||
<!-- Tailwind CSS - CDN Version -->
|
<!-- Tailwind CSS - Beide Optionen verfügbar -->
|
||||||
<script src="https://cdn.tailwindcss.com" nonce="{{ csp_nonce }}"></script>
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
<script nonce="{{ csp_nonce }}">
|
<!-- Alternative lokale Version, falls die CDN-Version blockiert wird -->
|
||||||
|
<link href="{{ url_for('static', filename='css/tailwind.min.css') }}" rel="stylesheet">
|
||||||
|
<script>
|
||||||
tailwind.config = {
|
tailwind.config = {
|
||||||
darkMode: 'class',
|
darkMode: 'class',
|
||||||
theme: {
|
theme: {
|
||||||
@@ -79,88 +81,32 @@
|
|||||||
<!-- Base-Styles ausgelagert in eigene Datei -->
|
<!-- Base-Styles ausgelagert in eigene Datei -->
|
||||||
<link href="{{ url_for('static', filename='css/base-styles.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='css/base-styles.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
<!-- Alpine.js - Self-hosted -->
|
<!-- Alpine.js - CDN Version -->
|
||||||
<script src="{{ url_for('static', filename='js/alpine.min.js') }}" defer nonce="{{ csp_nonce }}"></script>
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.3/dist/cdn.min.js"></script>
|
||||||
|
|
||||||
<!-- Neural Network Background CSS -->
|
<!-- Neural Network Background CSS -->
|
||||||
<link href="{{ url_for('static', filename='css/neural-network-background.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='css/neural-network-background.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- D3.js für Visualisierungen -->
|
||||||
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
|
|
||||||
|
<!-- Marked.js für Markdown-Parsing -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
|
|
||||||
|
<!-- ChatGPT Assistant -->
|
||||||
|
<script src="{{ url_for('static', filename='js/modules/chatgpt-assistant.js') }}"></script>
|
||||||
|
|
||||||
|
<!-- MindMap Visualization Module -->
|
||||||
|
<script src="{{ url_for('static', filename='js/modules/mindmap.js') }}"></script>
|
||||||
|
|
||||||
|
<!-- MindMap Page Module -->
|
||||||
|
<script src="{{ url_for('static', filename='js/modules/mindmap-page.js') }}"></script>
|
||||||
|
|
||||||
<!-- Neural Network Background Script -->
|
<!-- Neural Network Background Script -->
|
||||||
<script src="{{ url_for('static', filename='neural-network-background.js') }}" nonce="{{ csp_nonce }}"></script>
|
<script src="{{ url_for('static', filename='neural-network-background.js') }}"></script>
|
||||||
|
|
||||||
<!-- Hauptmodul laden (als ES6 Modul) -->
|
<!-- Hauptmodul laden (als traditionelles Skript) -->
|
||||||
<script type="module" nonce="{{ csp_nonce }}">
|
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||||
import MindMap from "{{ url_for('static', filename='js/main.js') }}";
|
|
||||||
// Alpine.js-Integration
|
|
||||||
document.addEventListener('alpine:init', () => {
|
|
||||||
Alpine.data('layout', () => ({
|
|
||||||
darkMode: true, // Default to dark mode
|
|
||||||
mobileMenuOpen: false, // Mobile Menü standardmäßig geschlossen
|
|
||||||
userMenuOpen: false,
|
|
||||||
showSettingsModal: false,
|
|
||||||
|
|
||||||
init() {
|
|
||||||
this.fetchDarkModeFromSession();
|
|
||||||
},
|
|
||||||
|
|
||||||
fetchDarkModeFromSession() {
|
|
||||||
// Lade den Dark Mode-Status vom Server
|
|
||||||
fetch('/api/get_dark_mode')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
|
||||||
this.darkMode = data.darkMode === 'true';
|
|
||||||
document.querySelector('html').classList.toggle('dark', this.darkMode);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Fehler beim Laden der Dark Mode-Einstellung:', error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleDarkMode() {
|
|
||||||
this.darkMode = !this.darkMode;
|
|
||||||
document.querySelector('html').classList.toggle('dark', this.darkMode);
|
|
||||||
|
|
||||||
// Speichere den Dark Mode-Status auf dem Server
|
|
||||||
fetch('/api/set_dark_mode', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ darkMode: this.darkMode })
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
|
||||||
// Zusätzlich im localStorage speichern für sofortige Reaktion bei Seitenwechsel
|
|
||||||
localStorage.setItem('darkMode', this.darkMode ? 'dark' : 'light');
|
|
||||||
// Event auslösen für andere Komponenten
|
|
||||||
document.dispatchEvent(new CustomEvent('darkModeToggled', {
|
|
||||||
detail: { isDark: this.darkMode }
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
console.error('Fehler beim Speichern der Dark Mode-Einstellung:', data.error);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Fehler beim Speichern der Dark Mode-Einstellung:', error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Setze einen globalen Alpine-Initialisierer
|
|
||||||
window.addEventListener('DOMContentLoaded', () => {
|
|
||||||
// Fallback für Alpine-Initialisierung
|
|
||||||
if (typeof Alpine !== 'undefined' && !document.body.hasAttribute('x-data')) {
|
|
||||||
document.body.setAttribute('x-data', 'layout()');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// MindMap global verfügbar machen (für Alpine.js und andere nicht-Module Skripte)
|
|
||||||
window.MindMap = MindMap;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Seitenspezifische Styles -->
|
<!-- Seitenspezifische Styles -->
|
||||||
{% block extra_css %}{% endblock %}
|
{% block extra_css %}{% endblock %}
|
||||||
@@ -243,7 +189,57 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ request.endpoint }}" class="relative overflow-x-hidden dark bg-gray-900 text-white" x-data="layout()">
|
<body data-page="{{ request.endpoint }}" class="relative overflow-x-hidden dark bg-gray-900 text-white" x-data="{
|
||||||
|
darkMode: true,
|
||||||
|
mobileMenuOpen: false,
|
||||||
|
userMenuOpen: false,
|
||||||
|
showSettingsModal: false,
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.fetchDarkModeFromSession();
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchDarkModeFromSession() {
|
||||||
|
fetch('/api/get_dark_mode')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
this.darkMode = data.darkMode === 'true';
|
||||||
|
document.querySelector('html').classList.toggle('dark', this.darkMode);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Fehler beim Laden der Dark Mode-Einstellung:', error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleDarkMode() {
|
||||||
|
this.darkMode = !this.darkMode;
|
||||||
|
document.querySelector('html').classList.toggle('dark', this.darkMode);
|
||||||
|
|
||||||
|
fetch('/api/set_dark_mode', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ darkMode: this.darkMode })
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
localStorage.setItem('darkMode', this.darkMode ? 'dark' : 'light');
|
||||||
|
document.dispatchEvent(new CustomEvent('darkModeToggled', {
|
||||||
|
detail: { isDark: this.darkMode }
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
console.error('Fehler beim Speichern der Dark Mode-Einstellung:', data.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Fehler beim Speichern der Dark Mode-Einstellung:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}">
|
||||||
<!-- App-Container -->
|
<!-- App-Container -->
|
||||||
<div id="app-container" class="flex flex-col min-h-screen">
|
<div id="app-container" class="flex flex-col min-h-screen">
|
||||||
<!-- Hauptnavigation -->
|
<!-- Hauptnavigation -->
|
||||||
@@ -597,11 +593,9 @@
|
|||||||
{% block scripts %}{% endblock %}
|
{% block scripts %}{% endblock %}
|
||||||
|
|
||||||
<!-- KI-Chat Initialisierung -->
|
<!-- KI-Chat Initialisierung -->
|
||||||
<script type="module" nonce="{{ csp_nonce }}">
|
<script>
|
||||||
// Importiere und initialisiere den ChatGPT-Assistenten direkt, um sicherzustellen,
|
// Initialisiere den ChatGPT-Assistenten direkt, um sicherzustellen,
|
||||||
// dass er auf jeder Seite verfügbar ist, selbst wenn MindMap nicht geladen ist
|
// dass er auf jeder Seite verfügbar ist, selbst wenn MindMap nicht geladen ist
|
||||||
import ChatGPTAssistant from "{{ url_for('static', filename='js/modules/chatgpt-assistant.js') }}";
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Prüfen, ob der Assistent bereits durch MindMap initialisiert wurde
|
// Prüfen, ob der Assistent bereits durch MindMap initialisiert wurde
|
||||||
if (!window.MindMap || !window.MindMap.assistant) {
|
if (!window.MindMap || !window.MindMap.assistant) {
|
||||||
|
|||||||
@@ -391,7 +391,7 @@
|
|||||||
<div id="mindmap-canvas"></div>
|
<div id="mindmap-canvas"></div>
|
||||||
|
|
||||||
<!-- Control Panel -->
|
<!-- Control Panel -->
|
||||||
<div class="control-panel p-4 w-64" id="control-panel" x-data="{ isExpanded: true }">
|
<div class="control-panel p-4 w-64">
|
||||||
<div class="panel-toggle" @click="isExpanded = !isExpanded">
|
<div class="panel-toggle" @click="isExpanded = !isExpanded">
|
||||||
<i class="fa-solid" :class="isExpanded ? 'fa-chevron-left' : 'fa-chevron-right'"></i>
|
<i class="fa-solid" :class="isExpanded ? 'fa-chevron-left' : 'fa-chevron-right'"></i>
|
||||||
</div>
|
</div>
|
||||||
@@ -432,7 +432,7 @@
|
|||||||
|
|
||||||
<!-- User Mindmaps Section -->
|
<!-- User Mindmaps Section -->
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
<div class="user-mindmap-section p-4 w-64" x-data="{ isExpanded: true }">
|
<div class="user-mindmap-section p-4 w-64">
|
||||||
<div class="flex items-center justify-between mb-4">
|
<div class="flex items-center justify-between mb-4">
|
||||||
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">Meine Mindmaps</h2>
|
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">Meine Mindmaps</h2>
|
||||||
<button @click="isExpanded = !isExpanded" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200">
|
<button @click="isExpanded = !isExpanded" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200">
|
||||||
|
|||||||
Reference in New Issue
Block a user