feat: update app logic and improve mindmap functionality

This commit is contained in:
2025-05-12 18:56:49 +01:00
parent b1d33ce643
commit a1bd999c6a
4 changed files with 1248 additions and 366 deletions

757
app.py
View File

@@ -277,7 +277,7 @@ def create_default_categories():
"icon": "fa-palette",
"subcategories": [
{"name": "Literatur", "description": "Schriftliche Werke", "icon": "fa-book"},
{"name": "Musik", "description": "Klangkunst", "icon": "fa-music"},
{"name": "Musik", "description": "Klangkunst", "icon": "fa-musik"},
{"name": "Bildende Kunst", "description": "Visuelle Kunstformen", "icon": "fa-paint-brush"}
]
},
@@ -2342,11 +2342,10 @@ if __name__ == '__main__':
db.create_all()
socketio.run(app, debug=True, host='0.0.0.0')
@app.route('/api/refresh-mindmap')
def refresh_mindmap():
@app.route('/api/mindmap/science')
def get_science_mindmap():
"""
API-Endpunkt zum Neuladen der Mindmap-Daten,
wenn die Datenbank-Verbindung vorübergehend fehlgeschlagen ist
API-Endpunkt für die Wissenschaft-Mindmap
"""
try:
# Stelle sicher, dass wir Kategorien haben
@@ -2430,47 +2429,268 @@ def refresh_mindmap():
'error': 'Datenbankverbindung konnte nicht hergestellt werden'
}), 500
# Die Route '/mindmap' wird bereits in Zeile 474 definiert - doppelte Definition entfernt
@app.route('/api/mindmap/technology')
def get_technology_mindmap():
"""
API-Endpunkt für die Technologie-Mindmap
"""
try:
# Stelle sicher, dass wir Kategorien haben
if Category.query.count() == 0:
create_default_categories()
# Überprüfe, ob wir bereits einen "Wissen"-Knoten haben
wissen_node = MindMapNode.query.filter_by(name="Wissen").first()
# Wenn kein "Wissen"-Knoten existiert, erstelle ihn
if not wissen_node:
wissen_node = MindMapNode(
name="Wissen",
description="Zentrale Wissensbasis",
color_code="#4299E1",
is_public=True
)
db.session.add(wissen_node)
db.session.commit()
# Hole alle Kategorien und Knoten
categories = Category.query.filter_by(parent_id=None).all()
category_tree = [build_category_tree(cat) for cat in categories]
# Hole alle Mindmap-Knoten außer dem "Wissen"-Knoten
nodes = MindMapNode.query.filter(MindMapNode.id != wissen_node.id).all()
# Vorbereiten der Node- und Edge-Arrays für die Antwort
node_data = []
edge_data = []
# Zuerst den "Wissen"-Knoten hinzufügen
node_data.append({
'id': wissen_node.id,
'name': wissen_node.name,
'description': wissen_node.description or '',
'color_code': wissen_node.color_code or '#4299E1',
'thought_count': len(wissen_node.thoughts),
'category_id': wissen_node.category_id
})
# Dann die anderen Knoten
for node in nodes:
node_obj = {
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'thought_count': len(node.thoughts),
'category_id': node.category_id
}
# Verbinde alle Top-Level-Knoten mit dem Wissen-Knoten
if not node.parents.all():
edge_data.append({
'source': wissen_node.id,
'target': node.id
})
# Verbindungen zwischen vorhandenen Knoten hinzufügen
node_children = node.children.all()
for child in node_children:
edge_data.append({
'source': node.id,
'target': child.id
})
node_data.append(node_obj)
return jsonify({
'success': True,
'categories': category_tree,
'nodes': node_data,
'edges': edge_data
})
except Exception as e:
print(f"Fehler beim Neuladen der Mindmap: {str(e)}")
return jsonify({
'success': False,
'error': 'Datenbankverbindung konnte nicht hergestellt werden'
}), 500
# Weiterleitung für Community/Forum-Routen
@app.route('/community')
@app.route('/Community')
@app.route('/forum')
@app.route('/Forum')
@app.route('/community_forum')
def redirect_community():
"""Leitet alle Community/Forum-URLs zur Startseite um"""
return redirect(url_for('index'))
@app.route('/api/mindmap/arts')
def get_arts_mindmap():
"""
API-Endpunkt für die Künste-Mindmap
"""
try:
# Stelle sicher, dass wir Kategorien haben
if Category.query.count() == 0:
create_default_categories()
# Überprüfe, ob wir bereits einen "Wissen"-Knoten haben
wissen_node = MindMapNode.query.filter_by(name="Wissen").first()
# Wenn kein "Wissen"-Knoten existiert, erstelle ihn
if not wissen_node:
wissen_node = MindMapNode(
name="Wissen",
description="Zentrale Wissensbasis",
color_code="#4299E1",
is_public=True
)
db.session.add(wissen_node)
db.session.commit()
# Hole alle Kategorien und Knoten
categories = Category.query.filter_by(parent_id=None).all()
category_tree = [build_category_tree(cat) for cat in categories]
# Hole alle Mindmap-Knoten außer dem "Wissen"-Knoten
nodes = MindMapNode.query.filter(MindMapNode.id != wissen_node.id).all()
# Vorbereiten der Node- und Edge-Arrays für die Antwort
node_data = []
edge_data = []
# Zuerst den "Wissen"-Knoten hinzufügen
node_data.append({
'id': wissen_node.id,
'name': wissen_node.name,
'description': wissen_node.description or '',
'color_code': wissen_node.color_code or '#4299E1',
'thought_count': len(wissen_node.thoughts),
'category_id': wissen_node.category_id
})
# Dann die anderen Knoten
for node in nodes:
node_obj = {
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'thought_count': len(node.thoughts),
'category_id': node.category_id
}
# Verbinde alle Top-Level-Knoten mit dem Wissen-Knoten
if not node.parents.all():
edge_data.append({
'source': wissen_node.id,
'target': node.id
})
# Verbindungen zwischen vorhandenen Knoten hinzufügen
node_children = node.children.all()
for child in node_children:
edge_data.append({
'source': node.id,
'target': child.id
})
node_data.append(node_obj)
return jsonify({
'success': True,
'categories': category_tree,
'nodes': node_data,
'edges': edge_data
})
except Exception as e:
print(f"Fehler beim Neuladen der Mindmap: {str(e)}")
return jsonify({
'success': False,
'error': 'Datenbankverbindung konnte nicht hergestellt werden'
}), 500
@app.route('/static/js/mindmap-init.js')
def serve_mindmap_init_js():
"""Bedient die Mindmap-Initialisierungsdatei."""
return app.send_static_file('js/mindmap-init.js'), 200, {'Content-Type': 'application/javascript'}
# Datenbank-Update-Route (admin-geschützt)
@app.route('/admin/update-database', methods=['GET', 'POST'])
@admin_required
def admin_update_database():
"""Admin-Route zum Aktualisieren der Datenbank"""
message = None
success = None
if request.method == 'POST':
try:
import utils.update_db as update_db
update_success = update_db.update_user_table()
if update_success:
message = "Die Datenbank wurde erfolgreich aktualisiert."
success = True
else:
message = "Es gab ein Problem bei der Aktualisierung der Datenbank."
success = False
except Exception as e:
message = f"Fehler: {str(e)}"
success = False
return render_template('admin/update_database.html', message=message, success=success)
@app.route('/api/mindmap/philosophy')
def get_philosophy_mindmap():
"""
API-Endpunkt für die Philosophie-Mindmap
"""
try:
# Stelle sicher, dass wir Kategorien haben
if Category.query.count() == 0:
create_default_categories()
# Überprüfe, ob wir bereits einen "Wissen"-Knoten haben
wissen_node = MindMapNode.query.filter_by(name="Wissen").first()
# Wenn kein "Wissen"-Knoten existiert, erstelle ihn
if not wissen_node:
wissen_node = MindMapNode(
name="Wissen",
description="Zentrale Wissensbasis",
color_code="#4299E1",
is_public=True
)
db.session.add(wissen_node)
db.session.commit()
# Hole alle Kategorien und Knoten
categories = Category.query.filter_by(parent_id=None).all()
category_tree = [build_category_tree(cat) for cat in categories]
# Hole alle Mindmap-Knoten außer dem "Wissen"-Knoten
nodes = MindMapNode.query.filter(MindMapNode.id != wissen_node.id).all()
# Vorbereiten der Node- und Edge-Arrays für die Antwort
node_data = []
edge_data = []
# Zuerst den "Wissen"-Knoten hinzufügen
node_data.append({
'id': wissen_node.id,
'name': wissen_node.name,
'description': wissen_node.description or '',
'color_code': wissen_node.color_code or '#4299E1',
'thought_count': len(wissen_node.thoughts),
'category_id': wissen_node.category_id
})
# Dann die anderen Knoten
for node in nodes:
node_obj = {
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'thought_count': len(node.thoughts),
'category_id': node.category_id
}
# Verbinde alle Top-Level-Knoten mit dem Wissen-Knoten
if not node.parents.all():
edge_data.append({
'source': wissen_node.id,
'target': node.id
})
# Verbindungen zwischen vorhandenen Knoten hinzufügen
node_children = node.children.all()
for child in node_children:
edge_data.append({
'source': node.id,
'target': child.id
})
node_data.append(node_obj)
return jsonify({
'success': True,
'categories': category_tree,
'nodes': node_data,
'edges': edge_data
})
except Exception as e:
print(f"Fehler beim Neuladen der Mindmap: {str(e)}")
return jsonify({
'success': False,
'error': 'Datenbankverbindung konnte nicht hergestellt werden'
}), 500
# Generische Route für andere Mindmap-Knoten (muss nach den spezifischen Routen kommen)
@app.route('/api/mindmap/<node_id>')
def get_mindmap_data(node_id):
"""
@@ -2479,8 +2699,88 @@ def get_mindmap_data(node_id):
Daten werden aus der Datenbank abgerufen.
"""
if node_id == 'root':
return get_root_mindmap()
try:
# Stelle sicher, dass wir Kategorien haben
if Category.query.count() == 0:
create_default_categories()
# Überprüfe, ob wir bereits einen "Wissen"-Knoten haben
wissen_node = MindMapNode.query.filter_by(name="Wissen").first()
# Wenn kein "Wissen"-Knoten existiert, erstelle ihn
if not wissen_node:
wissen_node = MindMapNode(
name="Wissen",
description="Zentrale Wissensbasis",
color_code="#4299E1",
is_public=True
)
db.session.add(wissen_node)
db.session.commit()
# Hole alle Kategorien und Knoten
categories = Category.query.filter_by(parent_id=None).all()
category_tree = [build_category_tree(cat) for cat in categories]
# Hole alle Mindmap-Knoten außer dem "Wissen"-Knoten
nodes = MindMapNode.query.filter(MindMapNode.id != wissen_node.id).all()
# Vorbereiten der Node- und Edge-Arrays für die Antwort
node_data = []
edge_data = []
# Zuerst den "Wissen"-Knoten hinzufügen
node_data.append({
'id': wissen_node.id,
'name': wissen_node.name,
'description': wissen_node.description or '',
'color_code': wissen_node.color_code or '#4299E1',
'thought_count': len(wissen_node.thoughts),
'category_id': wissen_node.category_id
})
# Dann die anderen Knoten
for node in nodes:
node_obj = {
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'thought_count': len(node.thoughts),
'category_id': node.category_id
}
# Verbinde alle Top-Level-Knoten mit dem Wissen-Knoten
if not node.parents.all():
edge_data.append({
'source': wissen_node.id,
'target': node.id
})
# Verbindungen zwischen vorhandenen Knoten hinzufügen
node_children = node.children.all()
for child in node_children:
edge_data.append({
'source': node.id,
'target': child.id
})
node_data.append(node_obj)
return jsonify({
'success': True,
'categories': category_tree,
'nodes': node_data,
'edges': edge_data
})
except Exception as e:
app.logger.error(f"Fehler beim Laden der Root-Mindmap: {str(e)}")
return jsonify({
'success': False,
'error': 'Datenbankverbindung konnte nicht hergestellt werden'
}), 500
app.logger.info(f"Mindmap-Daten werden für Node '{node_id}' angefordert.")
try:
@@ -2491,49 +2791,66 @@ def get_mindmap_data(node_id):
# Unterkategorien einer Hauptkategorie anzeigen
category_id = node_id.replace('cat_', '')
try:
category_id = int(category_id)
category = Category.query.get(category_id)
category_id_int = int(category_id)
category = Category.query.get(category_id_int)
if not category:
app.logger.warning(f"Kategorie mit ID {category_id} nicht gefunden.")
return jsonify(fallback_data)
nodes = []
edges = []
# Unterkategorien dieser Kategorie
subcategories = Category.query.filter_by(parent_id=category_id).all()
for subcat in subcategories:
subcat_node = {
"id": f"subcat_{subcat.id}",
"name": subcat.name,
"description": subcat.description or f"Unterkategorie: {subcat.name}",
"category": category.name,
"has_children": True,
"color_code": subcat.color_code or category.color_code
}
nodes.append(subcat_node)
if category:
# Hole alle Unterkategorien
subcategories = Category.query.filter_by(parent_id=category_id_int).all()
# Verbindung von der Hauptkategorie zur Unterkategorie
edges.append({
"source_id": node_id,
"target_id": f"subcat_{subcat.id}",
"strength": 0.8
# Hole alle Knoten dieser Kategorie
nodes = MindMapNode.query.filter_by(category_id=category_id_int).all()
# Vorbereiten der Antwort
node_data = []
edge_data = []
# Kategorie-Knoten hinzufügen
node_data.append({
'id': f"cat_{category.id}",
'name': category.name,
'description': category.description or '',
'color_code': category.color_code or '#9F7AEA',
'is_category': True
})
# Unterkategorien als Knoten hinzufügen
for subcat in subcategories:
node_data.append({
'id': f"cat_{subcat.id}",
'name': subcat.name,
'description': subcat.description or '',
'color_code': subcat.color_code or '#9F7AEA',
'is_category': True
})
# Verbindung zur Hauptkategorie
edge_data.append({
'source': f"cat_{category.id}",
'target': f"cat_{subcat.id}"
})
# Mindmap-Knoten hinzufügen
for node in nodes:
node_data.append({
'id': node.id,
'name': node.name,
'description': node.description or '',
'color_code': node.color_code or '#9F7AEA',
'thought_count': len(node.thoughts)
})
# Verbindung zur Kategorie
edge_data.append({
'source': f"cat_{category.id}",
'target': node.id
})
return jsonify({
'success': True,
'nodes': node_data,
'edges': edge_data
})
# Wenn es keine Unterkategorien gibt, zeige verwandte Knoten
if not subcategories:
# Im Fallback-Modus zurückfallen
app.logger.info(f"Keine Unterkategorien für Kategorie {category.name} gefunden, verwende Fallback-Daten.")
return jsonify(fallback_data)
response = {
"nodes": nodes,
"edges": edges
}
return jsonify(response)
except (ValueError, TypeError):
app.logger.error(f"Ungültige Kategorie-ID: {category_id}")
@@ -2771,273 +3088,3 @@ def get_fallback_mindmap_data(node_id):
# Diese Routen wurden an den Anfang der Datei verschoben und werden nicht mehr benötigt
@app.route('/api/mindmap/science')
def get_science_mindmap():
"""
Gibt die Wissenschafts-Mindmap zurück für Frontend-Kompatibilität.
"""
app.logger.info("Wissenschafts-Mindmap-Daten werden angefordert.")
try:
nodes = [
{
"id": "physics",
"name": "Physik",
"description": "Lehre von der Materie und ihren Wechselwirkungen",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
},
{
"id": "biology",
"name": "Biologie",
"description": "Lehre von den Lebewesen und ihren Lebensprozessen",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
},
{
"id": "chemistry",
"name": "Chemie",
"description": "Wissenschaft von den Stoffen und ihren Reaktionen",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
}
]
edges = [
{"source_id": "science", "target_id": "physics", "strength": 0.8},
{"source_id": "science", "target_id": "biology", "strength": 0.8},
{"source_id": "science", "target_id": "chemistry", "strength": 0.8}
]
return jsonify({
"nodes": nodes,
"edges": edges
})
except Exception as e:
app.logger.error(f"Fehler beim Abrufen der Wissenschafts-Mindmap-Daten: {str(e)}")
return jsonify({"error": "Fehler beim Abrufen der Mindmap-Daten"}), 500
@app.route('/api/mindmap/root')
def get_root_mindmap():
"""
Gibt die Root-Mindmap zurück, um Kompatibilität mit dem Frontend sicherzustellen.
"""
app.logger.info("Root-Mindmap-Daten werden angefordert.")
try:
# Fallback-Daten
nodes = [
{
"id": "center",
"name": "Wissenskarte",
"description": "Zentrale Wissenskarte mit allen Hauptthemen",
"is_center": True,
"color_code": "#f5f5f5",
"has_children": True
},
{
"id": "philosophy",
"name": "Philosophie",
"description": "Die Lehre vom Denken und der Erkenntnis",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
},
{
"id": "science",
"name": "Wissenschaft",
"description": "Systematische Erforschung der Natur und Gesellschaft",
"category": "Wissenschaft",
"has_children": True,
"color_code": "#f4b400"
},
{
"id": "technology",
"name": "Technologie",
"description": "Anwendung wissenschaftlicher Erkenntnisse",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
},
{
"id": "arts",
"name": "Künste",
"description": "Kreativer Ausdruck und künstlerische Gestaltung",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
}
]
edges = [
{"source_id": "center", "target_id": "philosophy", "strength": 0.9},
{"source_id": "center", "target_id": "science", "strength": 0.9},
{"source_id": "center", "target_id": "technology", "strength": 0.9},
{"source_id": "center", "target_id": "arts", "strength": 0.9}
]
response = {
"nodes": nodes,
"edges": edges
}
return jsonify(response)
except Exception as e:
app.logger.error(f"Fehler beim Abrufen der Root-Mindmap-Daten: {str(e)}")
app.logger.error(f"Stack Trace: {traceback.format_exc()}")
return jsonify({"error": "Fehler beim Abrufen der Mindmap-Daten"}), 500
@app.route('/api/mindmap/technology')
def get_technology_mindmap():
"""
Gibt die Technologie-Mindmap zurück für Frontend-Kompatibilität.
"""
app.logger.info("Technologie-Mindmap-Daten werden angefordert.")
try:
nodes = [
{
"id": "ai",
"name": "Künstliche Intelligenz",
"description": "Maschinelles Lernen und intelligente Systeme",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
},
{
"id": "robotics",
"name": "Robotik",
"description": "Entwicklung und Steuerung von Robotern",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
},
{
"id": "quantum_computing",
"name": "Quantencomputing",
"description": "Computer basierend auf Quantenmechanik",
"category": "Technologie",
"has_children": True,
"color_code": "#0d47a1"
}
]
edges = [
{"source_id": "technology", "target_id": "ai", "strength": 0.8},
{"source_id": "technology", "target_id": "robotics", "strength": 0.8},
{"source_id": "technology", "target_id": "quantum_computing", "strength": 0.8}
]
return jsonify({
"nodes": nodes,
"edges": edges
})
except Exception as e:
app.logger.error(f"Fehler beim Abrufen der Technologie-Mindmap-Daten: {str(e)}")
return jsonify({"error": "Fehler beim Abrufen der Mindmap-Daten"}), 500
@app.route('/api/mindmap/arts')
def get_arts_mindmap():
"""
Gibt die Künste-Mindmap zurück für Frontend-Kompatibilität.
"""
app.logger.info("Künste-Mindmap-Daten werden angefordert.")
try:
nodes = [
{
"id": "visual_arts",
"name": "Bildende Kunst",
"description": "Malerei, Bildhauerei und andere visuelle Kunstformen",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
},
{
"id": "music",
"name": "Musik",
"description": "Tonkunst und musikalische Komposition",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
},
{
"id": "literature",
"name": "Literatur",
"description": "Schriftliche Kunstwerke und Poesie",
"category": "Künste",
"has_children": True,
"color_code": "#c2185b"
}
]
edges = [
{"source_id": "arts", "target_id": "visual_arts", "strength": 0.8},
{"source_id": "arts", "target_id": "music", "strength": 0.8},
{"source_id": "arts", "target_id": "literature", "strength": 0.8}
]
return jsonify({
"nodes": nodes,
"edges": edges
})
except Exception as e:
app.logger.error(f"Fehler beim Abrufen der Künste-Mindmap-Daten: {str(e)}")
return jsonify({"error": "Fehler beim Abrufen der Mindmap-Daten"}), 500
@app.route('/api/mindmap/philosophy')
def get_philosophy_mindmap():
"""
Gibt die Philosophie-Mindmap zurück für Frontend-Kompatibilität.
"""
app.logger.info("Philosophie-Mindmap-Daten werden angefordert.")
try:
nodes = [
{
"id": "epistemology",
"name": "Erkenntnistheorie",
"description": "Untersuchung der Natur und Grenzen menschlicher Erkenntnis",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
},
{
"id": "ethics",
"name": "Ethik",
"description": "Lehre vom moralisch richtigen Handeln",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
},
{
"id": "metaphysics",
"name": "Metaphysik",
"description": "Grundfragen des Seins und der Wirklichkeit",
"category": "Philosophie",
"has_children": True,
"color_code": "#9F7AEA"
}
]
edges = [
{"source_id": "philosophy", "target_id": "epistemology", "strength": 0.8},
{"source_id": "philosophy", "target_id": "ethics", "strength": 0.8},
{"source_id": "philosophy", "target_id": "metaphysics", "strength": 0.8}
]
return jsonify({
"nodes": nodes,
"edges": edges
})
except Exception as e:
app.logger.error(f"Fehler beim Abrufen der Philosophie-Mindmap-Daten: {str(e)}")
return jsonify({"error": "Fehler beim Abrufen der Mindmap-Daten"}), 500