Compare commits

...

3 Commits

10 changed files with 241 additions and 139 deletions

View File

@@ -3,15 +3,20 @@
- Implementierung von Content Security Policy (CSP) - UNTER KEINEN UMSTÄNDEN!
- Implementierung von Cross-Site Request Forgery (CSRF) Schutz
- Implementierung von Security Headers
- Verwendung von TypeScript anstelle von JavaScript
- Implementierung von OAuth oder anderen externen Authentifizierungsmethoden
# HÄUFIGE FEHLER:
- Verwendung der falschen Datenbank (die korrekte ist: database/systades.db)
- Falsche Pfadangaben bei statischen Dateien
- Vergessen der deutschen Spracheinstellungen in Templates
- 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
D
## Content Security Policy (CSP)
### Problem: Externe Ressourcen werden nicht geladen
@@ -29,6 +34,35 @@
```html
<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
**Fehler:** Tailwind CSS kann nicht von CDN geladen werden.
@@ -62,3 +96,78 @@
**Lösung:**
1. Standard-Admin-Benutzer erstellen: `python TOOLS.py user:admin`
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
View File

@@ -73,7 +73,7 @@ def inject_globals():
'current_year': datetime.now().year
}
# Kontext-Prozessor für alle Templates
# Context-Prozessor für alle Templates
@app.context_processor
def inject_current_year():
return {'current_year': datetime.now().year}

View File

@@ -1,16 +1,6 @@
/*
* Tailwind CSS v3.4.16
*
* 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
/**
* 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
*/
/* Base Tailwind imports */
@tailwind base;
@tailwind components;
@tailwind utilities;
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');

File diff suppressed because one or more lines are too long

View File

@@ -2,9 +2,6 @@
* MindMap - Hauptdatei für globale JavaScript-Funktionen
*/
// Import des ChatGPT-Assistenten
import ChatGPTAssistant from './modules/chatgpt-assistant.js';
/**
* Hauptmodul für die MindMap-Anwendung
* Verwaltet die globale Anwendungslogik
@@ -38,10 +35,12 @@ const MindMap = {
console.log('MindMap-Anwendung wird initialisiert...');
// Initialisiere den ChatGPT-Assistenten
if (typeof ChatGPTAssistant !== 'undefined') {
const assistant = new ChatGPTAssistant();
assistant.init();
// Speichere als Teil von MindMap
this.assistant = assistant;
}
// Seiten-spezifische Initialisierer aufrufen
if (this.currentPage && this.pageInitializers[this.currentPage]) {
@@ -74,6 +73,12 @@ const MindMap = {
try {
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
const mindmap = new MindMapVisualization('#mindmap-container', {
height: mindmapContainer.clientHeight || 600,
@@ -227,6 +232,3 @@ const MindMap = {
// Globale Export für andere Module
window.MindMap = MindMap;
// Export als Modul
export default MindMap;

View File

@@ -568,5 +568,5 @@ class ChatGPTAssistant {
}
}
// Exportiere die Klasse für die Verwendung in anderen Modulen
export default ChatGPTAssistant;
// Mache die Klasse global verfügbar
window.ChatGPTAssistant = ChatGPTAssistant;

View File

@@ -3,12 +3,18 @@
* Spezifische Funktionen für die Mindmap-Seite
*/
document.addEventListener('DOMContentLoaded', function() {
// Registriere den Initialisierer im MindMap-Objekt
if (window.MindMap) {
window.MindMap.pageInitializers.mindmap = initMindmapPage;
}
// Füge das Modul zum globalen MindMap-Objekt hinzu
if (!window.MindMap) {
window.MindMap = {};
}
// 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
if (document.body.dataset.page === 'mindmap') {
initMindmapPage();
@@ -461,13 +467,13 @@ function initMindmapPage() {
// Erfolgsbenachrichtigung
if (window.MindMap && window.MindMap.showNotification) {
MindMap.showNotification('Gedanke erfolgreich gespeichert.', 'success');
window.MindMap.showNotification('Gedanke erfolgreich gespeichert.', 'success');
}
} catch (error) {
console.error('Fehler beim Speichern:', error);
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) {
try {
@@ -505,7 +511,11 @@ window.showComments = async function(thoughtId) {
} catch (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) {
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.');
}
}
};

View File

@@ -14,9 +14,11 @@
<meta name="keywords" content="systades, wissen, visualisierung, lernen, gedanken, theorie">
<meta name="author" content="Systades-Team">
<!-- Tailwind CSS - CDN Version -->
<script src="https://cdn.tailwindcss.com" nonce="{{ csp_nonce }}"></script>
<script nonce="{{ csp_nonce }}">
<!-- Tailwind CSS - Beide Optionen verfügbar -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Alternative lokale Version, falls die CDN-Version blockiert wird -->
<link href="{{ url_for('static', filename='css/tailwind.min.css') }}" rel="stylesheet">
<script>
tailwind.config = {
darkMode: 'class',
theme: {
@@ -79,88 +81,32 @@
<!-- Base-Styles ausgelagert in eigene Datei -->
<link href="{{ url_for('static', filename='css/base-styles.css') }}" rel="stylesheet">
<!-- Alpine.js - Self-hosted -->
<script src="{{ url_for('static', filename='js/alpine.min.js') }}" defer nonce="{{ csp_nonce }}"></script>
<!-- Alpine.js - CDN Version -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.3/dist/cdn.min.js"></script>
<!-- Neural Network Background CSS -->
<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 -->
<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) -->
<script type="module" nonce="{{ csp_nonce }}">
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>
<!-- Hauptmodul laden (als traditionelles Skript) -->
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
<!-- Seitenspezifische Styles -->
{% block extra_css %}{% endblock %}
@@ -243,7 +189,57 @@
}
</style>
</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 -->
<div id="app-container" class="flex flex-col min-h-screen">
<!-- Hauptnavigation -->
@@ -597,11 +593,9 @@
{% block scripts %}{% endblock %}
<!-- KI-Chat Initialisierung -->
<script type="module" nonce="{{ csp_nonce }}">
// Importiere und initialisiere den ChatGPT-Assistenten direkt, um sicherzustellen,
<script>
// Initialisiere den ChatGPT-Assistenten direkt, um sicherzustellen,
// 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() {
// Prüfen, ob der Assistent bereits durch MindMap initialisiert wurde
if (!window.MindMap || !window.MindMap.assistant) {

View File

@@ -391,7 +391,7 @@
<div id="mindmap-canvas"></div>
<!-- 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">
<i class="fa-solid" :class="isExpanded ? 'fa-chevron-left' : 'fa-chevron-right'"></i>
</div>
@@ -432,7 +432,7 @@
<!-- User Mindmaps Section -->
{% 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">
<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">