Compare commits

...

18 Commits

Author SHA1 Message Date
4aba72efa2 Merge branch 'main' of https://git.clickcandit.com/marwinm/website 2025-04-29 20:52:11 +01:00
89476d5353 w 2025-04-29 20:51:49 +01:00
0f7a33340a Update mindmap database: replace binary file with a new version to reflect recent changes in structure and data. 2025-04-27 08:56:56 +01:00
73501e7cda Add Flask server startup scripts: introduce start_server.bat for Windows and start-flask-server.py for enhanced server management. Update run.py to include logging and threaded request handling. Add test_server.py for server accessibility testing. 2025-04-25 17:09:09 +01:00
9f8eba6736 Refactor database initialization: streamline the process by removing the old init_database function, implementing a new structure for database setup, and ensuring the creation of a comprehensive mindmap hierarchy with an admin user. Update app.py to run on port 5000 instead of 6000. 2025-04-21 18:43:58 +01:00
b6bf9f387d Update mindmap database: replace binary file with a new version to incorporate recent structural and data changes. 2025-04-21 18:26:41 +01:00
d9fe1f8efc Update mindmap database: replace existing binary file with a new version, reflecting recent changes in mindmap structure and data. 2025-04-20 20:28:51 +01:00
fd7bc59851 Add user authentication routes: implement login, registration, and logout functionality, along with user profile and admin routes. Enhance mindmap API with error handling and default node creation. 2025-04-20 19:58:27 +01:00
55f1f87509 Refactor app initialization: encapsulate Flask app setup and database initialization within a create_app function, improving modularity and error handling during startup. 2025-04-20 19:54:07 +01:00
03f8761312 Update Docker configuration to change exposed port from 5000 to 6000 in Dockerfile and docker-compose.yml, ensuring consistency across the application. 2025-04-20 19:48:49 +01:00
506748fda7 Implement error handling and default node creation for mindmap routes; initialize database on first request to ensure root node exists. 2025-04-20 19:43:21 +01:00
6d069f68cd Update requirements.txt to include new dependencies for enhanced functionality and remove outdated packages for better compatibility. 2025-04-20 19:32:32 +01:00
4310239a7a Enhance Dockerfile: add system dependencies for building Python packages, update requirements.txt to remove specific version constraints, and verify installations with pip list. 2025-04-20 19:31:13 +01:00
e9fe907af0 Update requirements.txt to include email_validator==2.1.1 for improved email validation functionality. 2025-04-20 19:29:19 +01:00
0c69d9aba3 Remove unnecessary 'force' option from docker-compose.yml for cleaner configuration. 2025-04-20 19:26:44 +01:00
6da85cdece Refactor Docker setup: update docker-compose.yml to use a specific website directory for volumes, enable automatic restarts, and modify Dockerfile to clean up and copy application files more efficiently. 2025-04-20 19:25:08 +01:00
a073b09115 Update Docker configuration: change Docker Compose version to 3.8, enhance web service setup with context and dockerfile specifications, add volume and environment variables for Flask development, and modify Dockerfile to use Python 3.11 and improve file copying and command execution. 2025-04-20 19:22:08 +01:00
f1f4870989 Update dependencies in requirements.txt to specific versions for Flask, Flask-Login, Flask-SQLAlchemy, Werkzeug, and SQLAlchemy 2025-04-20 19:16:34 +01:00
21 changed files with 2802 additions and 330 deletions

View File

@@ -1,10 +1,27 @@
FROM python:3.9-slim-buster FROM python:3.11-slim
WORKDIR /app WORKDIR /app
COPY requirements.txt requirements.txt # System dependencies
RUN pip install -r requirements.txt RUN apt-get update && apt-get install -y \
gcc \
python3-dev \
libffi-dev \
&& rm -rf /var/lib/apt/lists/*
COPY website . # Clean up and install requirements
RUN rm -rf /app/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt \
&& pip install --no-cache-dir wheel setuptools
CMD ["python", "app.py"] # Copy application files
COPY website/ ./website/
COPY requirements.txt .
EXPOSE 6000
# Verify installations
RUN pip list
CMD ["python", "website/app.py"]

BIN
database/systades.db Normal file

Binary file not shown.

View File

@@ -1,7 +1,16 @@
version: "3.9" version: '3.8'
services: services:
web: web:
build: . build:
context: .
dockerfile: Dockerfile
ports: ports:
- "5000:5000" - "6000:6000"
volumes:
- ./website:/app/website
environment:
- FLASK_ENV=development
- FLASK_DEBUG=1
command: python website/app.py
restart: always restart: always

BIN
instance/mindmap.db Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
flask Flask
flask-login Flask-Login
flask-wtf Flask-SQLAlchemy
email-validator Werkzeug
python-dotenv SQLAlchemy
flask-sqlalchemy email_validator

119
start-flask-server.py Normal file
View File

@@ -0,0 +1,119 @@
#!/usr/bin/env python3
import os
import sys
import time
import subprocess
import webbrowser
import requests
import socket
import logging
from pathlib import Path
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
def is_port_in_use(port):
"""Check if a port is already in use"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
return s.connect_ex(('127.0.0.1', port)) == 0
def wait_for_server(url, max_attempts=5, delay=1):
"""Wait for the server to start responding"""
for i in range(max_attempts):
try:
response = requests.get(url, timeout=2)
if response.status_code == 200:
logger.info(f"Server is up and running at {url}")
return True
except requests.exceptions.RequestException:
logger.info(f"Waiting for server to start (attempt {i+1}/{max_attempts})...")
time.sleep(delay)
return False
def main():
# Get the current directory
current_dir = Path(__file__).parent.absolute()
website_dir = current_dir / 'website'
# Check if website directory exists
if not website_dir.exists():
logger.error(f"Website directory not found: {website_dir}")
return False
# Flask server details
host = "127.0.0.1"
port = 5000
url = f"http://{host}:{port}"
# Check if the port is already in use
if is_port_in_use(port):
logger.warning(f"Port {port} is already in use. There might be another server running.")
answer = input("Would you like to try to connect to the existing server? (y/n): ")
if answer.lower() == 'y':
webbrowser.open(url)
return True
else:
logger.info("Please stop the other server and try again.")
return False
# Path to the run.py script
run_script = website_dir / 'run.py'
# Check if run.py exists
if not run_script.exists():
logger.error(f"Run script not found: {run_script}")
return False
# Start the Flask server in a separate process
logger.info(f"Starting Flask server from {run_script}...")
try:
# Use Python executable from the current environment
python_exe = sys.executable
# Start the server as a separate process
server_process = subprocess.Popen(
[python_exe, str(run_script)],
cwd=str(website_dir),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1
)
# Wait for server to start
server_started = wait_for_server(url, max_attempts=10, delay=2)
if server_started:
logger.info("Opening web browser...")
webbrowser.open(url)
# Keep the server running and display its output
logger.info("Server is running. Press Ctrl+C to stop.")
try:
for line in server_process.stdout:
print(line.strip())
except KeyboardInterrupt:
logger.info("Stopping server...")
server_process.terminate()
return True
else:
logger.error("Failed to start the server or server not responding")
server_process.terminate()
return False
except Exception as e:
logger.error(f"Error starting Flask server: {e}")
return False
if __name__ == "__main__":
success = main()
if not success:
print("\nPress Enter to exit...")
input()
sys.exit(0 if success else 1)

72
start.sh Normal file
View File

@@ -0,0 +1,72 @@
#!/bin/bash
# Farben für die Ausgabe
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Funktion zum Anzeigen des Hilfetexts
show_help() {
echo -e "${YELLOW}Verwendung: ./start.sh [Option]${NC}"
echo "Optionen:"
echo " start - Startet die Container"
echo " stop - Stoppt die Container"
echo " restart - Neustart der Container"
echo " rebuild - Baut die Container neu"
echo " clean - Entfernt alle Container und Images"
echo " logs - Zeigt die Container-Logs"
echo " help - Zeigt diese Hilfe"
}
# Prüfen ob Docker läuft
check_docker() {
if ! docker info > /dev/null 2>&1; then
echo -e "${RED}Error: Docker ist nicht gestartet${NC}"
exit 1
fi
}
case "$1" in
start)
check_docker
echo -e "${GREEN}Starte Container...${NC}"
docker-compose up -d
echo -e "${GREEN}Container erfolgreich gestartet!${NC}"
;;
stop)
check_docker
echo -e "${YELLOW}Stoppe Container...${NC}"
docker-compose down
echo -e "${GREEN}Container erfolgreich gestoppt!${NC}"
;;
restart)
check_docker
echo -e "${YELLOW}Neustart der Container...${NC}"
docker-compose down
docker-compose up -d
echo -e "${GREEN}Container erfolgreich neugestartet!${NC}"
;;
rebuild)
check_docker
echo -e "${YELLOW}Baue Container neu...${NC}"
docker-compose down --rmi all
docker-compose build --no-cache
docker-compose up -d
echo -e "${GREEN}Container erfolgreich neu gebaut!${NC}"
;;
clean)
check_docker
echo -e "${RED}Entferne alle Container und Images...${NC}"
docker-compose down --rmi all -v
echo -e "${GREEN}Aufräumen abgeschlossen!${NC}"
;;
logs)
check_docker
echo -e "${YELLOW}Container-Logs:${NC}"
docker-compose logs -f
;;
help|*)
show_help
;;
esac

5
start_server.bat Normal file
View File

@@ -0,0 +1,5 @@
@echo off
cd website
echo Starting Flask server on http://127.0.0.1:5000
python run.py
pause

File diff suppressed because it is too large Load Diff

25
test_server.py Normal file
View File

@@ -0,0 +1,25 @@
import requests
import time
def test_flask_server():
"""Test if the Flask server is accessible at http://127.0.0.1:5000"""
url = "http://127.0.0.1:5000"
print(f"Testing connection to Flask server at {url}")
for i in range(3):
try:
response = requests.get(url, timeout=5)
print(f"SUCCESS! Status code: {response.status_code}")
return True
except requests.exceptions.RequestException as e:
print(f"Attempt {i+1} failed: {e}")
if i < 2:
print("Waiting 2 seconds and trying again...")
time.sleep(2)
print("Failed to connect to the Flask server after 3 attempts")
return False
if __name__ == "__main__":
test_flask_server()

Binary file not shown.

Binary file not shown.

View File

@@ -6,15 +6,231 @@ from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
import json import json
app = Flask(__name__) db = SQLAlchemy()
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'default-dev-key') login_manager = LoginManager()
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mindmap.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login' login_manager.login_view = 'login'
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'default-dev-key')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mindmap.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
login_manager.init_app(app)
with app.app_context():
# Initialize database and create root node
db.create_all()
try:
root = MindMapNode.query.filter_by(parent_id=None).first()
if not root:
root = MindMapNode(name="Wissenschaft")
db.session.add(root)
db.session.commit()
except Exception as e:
print(f"Error initializing database: {str(e)}")
# Register all routes with the app
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if user and user.check_password(password):
login_user(user)
next_page = request.args.get('next')
return redirect(next_page or url_for('index'))
flash('Ungültiger Benutzername oder Passwort')
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form.get('username')
email = request.form.get('email')
password = request.form.get('password')
if User.query.filter_by(username=username).first():
flash('Benutzername existiert bereits')
return redirect(url_for('register'))
if User.query.filter_by(email=email).first():
flash('E-Mail ist bereits registriert')
return redirect(url_for('register'))
user = User(username=username, email=email)
user.set_password(password)
db.session.add(user)
db.session.commit()
login_user(user)
return redirect(url_for('index'))
return render_template('register.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/')
def index():
return render_template('index.html')
@app.route('/mindmap')
def mindmap():
try:
root_node = MindMapNode.query.filter_by(parent_id=None).first()
if not root_node:
root_node = MindMapNode(name="Wissenschaft")
db.session.add(root_node)
db.session.commit()
return render_template('mindmap.html')
except Exception as e:
app.logger.error(f"Error loading mindmap: {str(e)}")
return render_template('mindmap.html', error="Fehler beim Laden der Mindmap. Bitte versuchen Sie es erneut.")
@app.route('/profile')
@login_required
def profile():
thoughts = Thought.query.filter_by(user_id=current_user.id).order_by(Thought.timestamp.desc()).all()
return render_template('profile.html', thoughts=thoughts)
@app.route('/api/mindmap')
def get_mindmap():
try:
root_nodes = MindMapNode.query.filter_by(parent_id=None).all()
def build_tree(node):
return {
'id': node.id,
'name': node.name,
'children': [build_tree(child) for child in node.children]
}
result = [build_tree(node) for node in root_nodes]
if not result:
root = MindMapNode(name="Wissenschaft")
db.session.add(root)
db.session.commit()
result = [build_tree(root)]
return jsonify(result)
except Exception as e:
app.logger.error(f"Error in get_mindmap: {str(e)}")
return jsonify({'error': 'Fehler beim Laden der Mindmap'}), 500
@app.route('/api/thoughts/<int:node_id>', methods=['GET'])
def get_thoughts(node_id):
node = MindMapNode.query.get_or_404(node_id)
thoughts = []
for thought in node.thoughts:
thoughts.append({
'id': thought.id,
'content': thought.content,
'author': thought.author.username,
'timestamp': thought.timestamp.strftime('%d.%m.%Y, %H:%M'),
'comments_count': len(thought.comments),
'branch': thought.branch
})
return jsonify(thoughts)
@app.route('/api/thoughts', methods=['POST'])
@login_required
def add_thought():
data = request.json
node_id = data.get('node_id')
content = data.get('content')
if not node_id or not content:
return jsonify({'error': 'Fehlende Daten'}), 400
node = MindMapNode.query.get_or_404(node_id)
thought = Thought(
content=content,
branch=node.name,
user_id=current_user.id
)
db.session.add(thought)
node.thoughts.append(thought)
db.session.commit()
return jsonify({
'id': thought.id,
'content': thought.content,
'author': thought.author.username,
'timestamp': thought.timestamp.strftime('%d.%m.%Y, %H:%M'),
'branch': thought.branch
})
@app.route('/api/comments/<int:thought_id>', methods=['GET'])
def get_comments(thought_id):
thought = Thought.query.get_or_404(thought_id)
comments = [
{
'id': comment.id,
'content': comment.content,
'author': comment.author.username,
'timestamp': comment.timestamp.strftime('%d.%m.%Y, %H:%M')
}
for comment in thought.comments
]
return jsonify(comments)
@app.route('/api/comments', methods=['POST'])
@login_required
def add_comment():
data = request.json
thought_id = data.get('thought_id')
content = data.get('content')
if not thought_id or not content:
return jsonify({'error': 'Fehlende Daten'}), 400
thought = Thought.query.get_or_404(thought_id)
comment = Comment(
content=content,
thought_id=thought_id,
user_id=current_user.id
)
db.session.add(comment)
db.session.commit()
return jsonify({
'id': comment.id,
'content': comment.content,
'author': comment.author.username,
'timestamp': comment.timestamp.strftime('%d.%m.%Y, %H:%M')
})
@app.route('/admin')
@login_required
def admin():
if not current_user.is_admin:
flash('Zugriff verweigert')
return redirect(url_for('index'))
users = User.query.all()
nodes = MindMapNode.query.all()
thoughts = Thought.query.all()
return render_template('admin.html', users=users, nodes=nodes, thoughts=thoughts)
return app
# Database Models # Database Models
class User(UserMixin, db.Model): class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
@@ -59,206 +275,6 @@ node_thought_association = db.Table('node_thought_association',
db.Column('thought_id', db.Integer, db.ForeignKey('thought.id'), primary_key=True) db.Column('thought_id', db.Integer, db.ForeignKey('thought.id'), primary_key=True)
) )
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
# Routes for authentication
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if user and user.check_password(password):
login_user(user)
next_page = request.args.get('next')
return redirect(next_page or url_for('index'))
flash('Ungültiger Benutzername oder Passwort')
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form.get('username')
email = request.form.get('email')
password = request.form.get('password')
if User.query.filter_by(username=username).first():
flash('Benutzername existiert bereits')
return redirect(url_for('register'))
if User.query.filter_by(email=email).first():
flash('E-Mail ist bereits registriert')
return redirect(url_for('register'))
user = User(username=username, email=email)
user.set_password(password)
db.session.add(user)
db.session.commit()
login_user(user)
return redirect(url_for('index'))
return render_template('register.html')
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
# Route for the homepage
@app.route('/')
def index():
return render_template('index.html')
# Route for the mindmap page
@app.route('/mindmap')
def mindmap():
return render_template('mindmap.html')
# Route for user profile
@app.route('/profile')
@login_required
def profile():
thoughts = Thought.query.filter_by(user_id=current_user.id).order_by(Thought.timestamp.desc()).all()
return render_template('profile.html', thoughts=thoughts)
# API routes for mindmap and thoughts
@app.route('/api/mindmap')
def get_mindmap():
root_nodes = MindMapNode.query.filter_by(parent_id=None).all()
def build_tree(node):
return {
'id': node.id,
'name': node.name,
'children': [build_tree(child) for child in node.children]
}
result = [build_tree(node) for node in root_nodes]
return jsonify(result)
@app.route('/api/thoughts/<int:node_id>', methods=['GET'])
def get_thoughts(node_id):
node = MindMapNode.query.get_or_404(node_id)
thoughts = []
for thought in node.thoughts:
thoughts.append({
'id': thought.id,
'content': thought.content,
'author': thought.author.username,
'timestamp': thought.timestamp.strftime('%d.%m.%Y, %H:%M'),
'comments_count': len(thought.comments),
'branch': thought.branch
})
return jsonify(thoughts)
@app.route('/api/thought/<int:thought_id>', methods=['GET'])
def get_thought(thought_id):
thought = Thought.query.get_or_404(thought_id)
return jsonify({
'id': thought.id,
'content': thought.content,
'author': thought.author.username,
'timestamp': thought.timestamp.strftime('%d.%m.%Y, %H:%M'),
'branch': thought.branch,
'comments_count': len(thought.comments)
})
@app.route('/api/thoughts', methods=['POST'])
@login_required
def add_thought():
data = request.json
node_id = data.get('node_id')
content = data.get('content')
if not node_id or not content:
return jsonify({'error': 'Fehlende Daten'}), 400
node = MindMapNode.query.get_or_404(node_id)
thought = Thought(
content=content,
branch=node.name,
user_id=current_user.id
)
db.session.add(thought)
node.thoughts.append(thought)
db.session.commit()
return jsonify({
'id': thought.id,
'content': thought.content,
'author': thought.author.username,
'timestamp': thought.timestamp.strftime('%d.%m.%Y, %H:%M'),
'branch': thought.branch
})
@app.route('/api/comments/<int:thought_id>', methods=['GET'])
def get_comments(thought_id):
thought = Thought.query.get_or_404(thought_id)
comments = [
{
'id': comment.id,
'content': comment.content,
'author': comment.author.username,
'timestamp': comment.timestamp.strftime('%d.%m.%Y, %H:%M')
}
for comment in thought.comments
]
return jsonify(comments)
@app.route('/api/comments', methods=['POST'])
@login_required
def add_comment():
data = request.json
thought_id = data.get('thought_id')
content = data.get('content')
if not thought_id or not content:
return jsonify({'error': 'Fehlende Daten'}), 400
thought = Thought.query.get_or_404(thought_id)
comment = Comment(
content=content,
thought_id=thought_id,
user_id=current_user.id
)
db.session.add(comment)
db.session.commit()
return jsonify({
'id': comment.id,
'content': comment.content,
'author': comment.author.username,
'timestamp': comment.timestamp.strftime('%d.%m.%Y, %H:%M')
})
# Admin routes
@app.route('/admin')
@login_required
def admin():
if not current_user.is_admin:
flash('Zugriff verweigert')
return redirect(url_for('index'))
users = User.query.all()
nodes = MindMapNode.query.all()
thoughts = Thought.query.all()
return render_template('admin.html', users=users, nodes=nodes, thoughts=thoughts)
# Flask starten
if __name__ == '__main__': if __name__ == '__main__':
with app.app_context(): app = create_app()
# Make sure tables exist app.run(host="0.0.0.0", port=5000, debug=True)
db.create_all()
app.run(host="0.0.0.0", debug=True)

View File

@@ -1,88 +1,144 @@
from app import app, db, User, MindMapNode import os
import sys
from pathlib import Path
import shutil
def init_database(): # Pfade zu möglichen Datenbankdateien
"""Initialize the database with admin user and mindmap structure.""" db_paths = [
with app.app_context(): Path("instance/mindmap.db"),
# Create all tables Path("mindmap.db"),
db.create_all() Path("website/instance/mindmap.db"),
Path("website/mindmap.db")
# Check if we already have users ]
if User.query.first() is None:
print("Creating admin user...")
# Create admin user
admin = User(username='admin', email='admin@example.com', is_admin=True)
admin.set_password('admin123')
db.session.add(admin)
# Create regular test user
test_user = User(username='test', email='test@example.com', is_admin=False)
test_user.set_password('test123')
db.session.add(test_user)
db.session.commit()
print("Admin user created successfully!")
# Check if we already have mindmap nodes
if MindMapNode.query.first() is None:
print("Creating initial mindmap structure...")
# Create initial mindmap structure
root = MindMapNode(name="Wissenschaftliche Mindmap")
db.session.add(root)
# Level 1 nodes
node1 = MindMapNode(name="Naturwissenschaften", parent=root)
node2 = MindMapNode(name="Geisteswissenschaften", parent=root)
node3 = MindMapNode(name="Technologie", parent=root)
node4 = MindMapNode(name="Künste", parent=root)
db.session.add_all([node1, node2, node3, node4])
# Level 2 nodes - Naturwissenschaften
node1_1 = MindMapNode(name="Physik", parent=node1)
node1_2 = MindMapNode(name="Biologie", parent=node1)
node1_3 = MindMapNode(name="Chemie", parent=node1)
node1_4 = MindMapNode(name="Astronomie", parent=node1)
db.session.add_all([node1_1, node1_2, node1_3, node1_4])
# Level 2 nodes - Geisteswissenschaften
node2_1 = MindMapNode(name="Philosophie", parent=node2)
node2_2 = MindMapNode(name="Geschichte", parent=node2)
node2_3 = MindMapNode(name="Psychologie", parent=node2)
node2_4 = MindMapNode(name="Soziologie", parent=node2)
db.session.add_all([node2_1, node2_2, node2_3, node2_4])
# Level 2 nodes - Technologie
node3_1 = MindMapNode(name="Informatik", parent=node3)
node3_2 = MindMapNode(name="Biotechnologie", parent=node3)
node3_3 = MindMapNode(name="Künstliche Intelligenz", parent=node3)
node3_4 = MindMapNode(name="Energietechnik", parent=node3)
db.session.add_all([node3_1, node3_2, node3_3, node3_4])
# Level 2 nodes - Künste
node4_1 = MindMapNode(name="Bildende Kunst", parent=node4)
node4_2 = MindMapNode(name="Musik", parent=node4)
node4_3 = MindMapNode(name="Literatur", parent=node4)
node4_4 = MindMapNode(name="Film", parent=node4)
db.session.add_all([node4_1, node4_2, node4_3, node4_4])
# Level 3 nodes - a few examples
# Physik
MindMapNode(name="Quantenphysik", parent=node1_1)
MindMapNode(name="Relativitätstheorie", parent=node1_1)
# Informatik
MindMapNode(name="Maschinelles Lernen", parent=node3_1)
MindMapNode(name="Softwareentwicklung", parent=node3_1)
MindMapNode(name="Datenbanken", parent=node3_1)
# Commit changes
db.session.commit()
print("Mindmap structure created successfully!")
print("Database initialization complete.")
if __name__ == "__main__": # Lösche bestehende Datenbankdateien
init_database() for db_path in db_paths:
print("You can now run the application with 'python app.py'") if db_path.exists():
print("Login with:") try:
print(" Admin: username=admin, password=admin123") print(f"Lösche Datenbank: {db_path}")
print(" User: username=test, password=test123") os.remove(db_path)
except Exception as e:
print(f"Fehler beim Löschen von {db_path}: {e}")
# Stelle sicher, dass das instance-Verzeichnis existiert
instance_dir = Path("instance")
if not instance_dir.exists():
os.makedirs(instance_dir)
# Importiere Datenbankmodelle und erstelle die Datenbank
from app import db, create_app, User, MindMapNode, Thought, Comment
app = create_app()
with app.app_context():
print("Erstelle neue Datenbank...")
db.drop_all() # Stelle sicher, dass alle Tabellen gelöscht sind
db.create_all() # Erstelle Tabellen basierend auf den Modellen
# Erstelle einen Admin-Benutzer
admin = User(username="admin", email="admin@example.com", is_admin=True)
admin.set_password("admin123")
db.session.add(admin)
# Erstelle Root-Node
root = MindMapNode(name="Wissenschaft")
db.session.add(root)
# Hauptkategorien erstellen
naturwissenschaften = MindMapNode(name="Naturwissenschaften", parent=root)
geisteswissenschaften = MindMapNode(name="Geisteswissenschaften", parent=root)
sozialwissenschaften = MindMapNode(name="Sozialwissenschaften", parent=root)
ingenieurwissenschaften = MindMapNode(name="Ingenieurwissenschaften", parent=root)
medizin = MindMapNode(name="Medizin", parent=root)
informatik = MindMapNode(name="Informatik", parent=root)
db.session.add_all([naturwissenschaften, geisteswissenschaften, sozialwissenschaften,
ingenieurwissenschaften, medizin, informatik])
# Unterkategorien für Naturwissenschaften
physik = MindMapNode(name="Physik", parent=naturwissenschaften)
chemie = MindMapNode(name="Chemie", parent=naturwissenschaften)
biologie = MindMapNode(name="Biologie", parent=naturwissenschaften)
astronomie = MindMapNode(name="Astronomie", parent=naturwissenschaften)
geologie = MindMapNode(name="Geologie", parent=naturwissenschaften)
# Unterkategorien für Physik
quantenphysik = MindMapNode(name="Quantenphysik", parent=physik)
relativitätstheorie = MindMapNode(name="Relativitätstheorie", parent=physik)
thermodynamik = MindMapNode(name="Thermodynamik", parent=physik)
# Unterkategorien für Geisteswissenschaften
philosophie = MindMapNode(name="Philosophie", parent=geisteswissenschaften)
geschichte = MindMapNode(name="Geschichte", parent=geisteswissenschaften)
linguistik = MindMapNode(name="Linguistik", parent=geisteswissenschaften)
literaturwissenschaft = MindMapNode(name="Literaturwissenschaft", parent=geisteswissenschaften)
religionswissenschaft = MindMapNode(name="Religionswissenschaft", parent=geisteswissenschaften)
# Unterkategorien für Sozialwissenschaften
soziologie = MindMapNode(name="Soziologie", parent=sozialwissenschaften)
psychologie = MindMapNode(name="Psychologie", parent=sozialwissenschaften)
politikwissenschaft = MindMapNode(name="Politikwissenschaft", parent=sozialwissenschaften)
wirtschaftswissenschaften = MindMapNode(name="Wirtschaftswissenschaften", parent=sozialwissenschaften)
# Unterkategorien für Ingenieurwissenschaften
maschinenbau = MindMapNode(name="Maschinenbau", parent=ingenieurwissenschaften)
elektrotechnik = MindMapNode(name="Elektrotechnik", parent=ingenieurwissenschaften)
bauingenieurwesen = MindMapNode(name="Bauingenieurwesen", parent=ingenieurwissenschaften)
verfahrenstechnik = MindMapNode(name="Verfahrenstechnik", parent=ingenieurwissenschaften)
# Unterkategorien für Medizin
humanmedizin = MindMapNode(name="Humanmedizin", parent=medizin)
zahnmedizin = MindMapNode(name="Zahnmedizin", parent=medizin)
pharmazie = MindMapNode(name="Pharmazie", parent=medizin)
neurologie = MindMapNode(name="Neurologie", parent=medizin)
onkologie = MindMapNode(name="Onkologie", parent=medizin)
# Unterkategorien für Informatik
künstliche_intelligenz = MindMapNode(name="Künstliche Intelligenz", parent=informatik)
datenbanken = MindMapNode(name="Datenbanken", parent=informatik)
softwareentwicklung = MindMapNode(name="Softwareentwicklung", parent=informatik)
computergrafik = MindMapNode(name="Computergrafik", parent=informatik)
cybersicherheit = MindMapNode(name="Cybersicherheit", parent=informatik)
# Alle Nodes zur Session hinzufügen
all_nodes = [physik, chemie, biologie, astronomie, geologie,
quantenphysik, relativitätstheorie, thermodynamik,
philosophie, geschichte, linguistik, literaturwissenschaft, religionswissenschaft,
soziologie, psychologie, politikwissenschaft, wirtschaftswissenschaften,
maschinenbau, elektrotechnik, bauingenieurwesen, verfahrenstechnik,
humanmedizin, zahnmedizin, pharmazie, neurologie, onkologie,
künstliche_intelligenz, datenbanken, softwareentwicklung, computergrafik, cybersicherheit]
db.session.add_all(all_nodes)
# Füge einen Beispiel-Gedanken hinzu
thought = Thought(
content="Dies ist ein Beispiel-Gedanke zur Wissenschaft allgemein.",
branch="Wissenschaft",
user_id=1 # Admin-Benutzer
)
db.session.add(thought)
root.thoughts.append(thought)
# Füge weitere Beispiel-Gedanken hinzu
thought_ai = Thought(
content="Künstliche Intelligenz transformiert viele Bereiche der Wissenschaft und Gesellschaft.",
branch="Künstliche Intelligenz",
user_id=1
)
db.session.add(thought_ai)
künstliche_intelligenz.thoughts.append(thought_ai)
thought_physik = Thought(
content="Die Quantenphysik stellt unser Verständnis der Realität grundlegend in Frage.",
branch="Quantenphysik",
user_id=1
)
db.session.add(thought_physik)
quantenphysik.thoughts.append(thought_physik)
db.session.commit()
print("Datenbank wurde erfolgreich initialisiert!")
print(f"Admin-Benutzer erstellt: admin/admin123")
print(f"Root-Node 'Wissenschaft' erstellt mit mehreren Hauptkategorien und Unterkategorien")

Binary file not shown.

View File

@@ -1,11 +1,20 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
from init_db import init_database import sys
from app import app import logging
from app import create_app
# Configure logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
app = create_app()
if __name__ == "__main__": if __name__ == "__main__":
# Initialize the database first logger.info("Starting Flask server on http://127.0.0.1:5000")
init_database() try:
# Use threaded=True for better request handling
# Run the Flask application app.run(host="127.0.0.1", port=5000, debug=True, use_reloader=False, threaded=True)
app.run(host="0.0.0.0", debug=True) except Exception as e:
logger.error(f"Error starting Flask server: {e}")
sys.exit(1)

View File

@@ -8,7 +8,7 @@
<div class="flex flex-col space-y-4 sm:flex-row sm:space-y-0 sm:space-x-4 justify-center"> <div class="flex flex-col space-y-4 sm:flex-row sm:space-y-0 sm:space-x-4 justify-center">
<a href="{{ url_for('mindmap') }}" class="bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 text-white font-semibold px-6 py-3 rounded-lg transition-all duration-300 transform hover:scale-105"> <a href="{{ url_for('mindmap') }}" class="bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 text-white font-semibold px-6 py-3 rounded-lg transition-all duration-300 transform hover:scale-105">
Starte die Mindmap Zum Netzwerk
</a> </a>
{% if not current_user.is_authenticated %} {% if not current_user.is_authenticated %}
<a href="{{ url_for('register') }}" class="glass hover:bg-white/20 text-white font-semibold px-6 py-3 rounded-lg transition-all duration-300 transform hover:scale-105"> <a href="{{ url_for('register') }}" class="glass hover:bg-white/20 text-white font-semibold px-6 py-3 rounded-lg transition-all duration-300 transform hover:scale-105">
@@ -20,19 +20,16 @@
<div class="mt-12 grid grid-cols-1 md:grid-cols-3 gap-6 w-full max-w-4xl"> <div class="mt-12 grid grid-cols-1 md:grid-cols-3 gap-6 w-full max-w-4xl">
<div class="glass p-6 text-white"> <div class="glass p-6 text-white">
<div class="text-3xl mb-2">🧠</div>
<h3 class="text-xl font-semibold mb-2">Visualisiere Wissen</h3> <h3 class="text-xl font-semibold mb-2">Visualisiere Wissen</h3>
<p class="text-white/80">Erkenne Zusammenhänge zwischen verschiedenen Wissensgebieten durch intuitive Mindmaps.</p> <p class="text-white/80">Erkenne Zusammenhänge zwischen verschiedenen Wissensgebieten durch intuitive Mindmaps.</p>
</div> </div>
<div class="glass p-6 text-white"> <div class="glass p-6 text-white">
<div class="text-3xl mb-2">💡</div>
<h3 class="text-xl font-semibold mb-2">Teile Gedanken</h3> <h3 class="text-xl font-semibold mb-2">Teile Gedanken</h3>
<p class="text-white/80">Füge deine eigenen Gedanken zu bestehenden Themen hinzu und bereichere die Community.</p> <p class="text-white/80">Füge deine eigenen Gedanken zu bestehenden Themen hinzu und bereichere die Community.</p>
</div> </div>
<div class="glass p-6 text-white"> <div class="glass p-6 text-white">
<div class="text-3xl mb-2">🔄</div>
<h3 class="text-xl font-semibold mb-2">Interaktive Vernetzung</h3> <h3 class="text-xl font-semibold mb-2">Interaktive Vernetzung</h3>
<p class="text-white/80">Beteilige dich an Diskussionen und sieh wie sich Ideen gemeinsam entwickeln.</p> <p class="text-white/80">Beteilige dich an Diskussionen und sieh wie sich Ideen gemeinsam entwickeln.</p>
</div> </div>

View File

@@ -99,6 +99,13 @@
.node:hover circle { .node:hover circle {
filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.8)); filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.8));
} }
/* Fix for "keine Auswahl" text */
#selected-node-title {
width: 100%;
overflow: visible;
word-wrap: break-word;
}
</style> </style>
{% endblock %} {% endblock %}
@@ -346,12 +353,21 @@
// Create hierarchical layout // Create hierarchical layout
const root = d3.hierarchy(data); const root = d3.hierarchy(data);
// Create tree layout // Create radial layout instead of tree for all-direction branches
const treeLayout = d3.tree() const radius = Math.min(width, height) / 2 - 100;
.size([height - 100, width - 200])
.nodeSize([80, 200]);
treeLayout(root); const radialLayout = d3.cluster()
.size([360, radius]);
radialLayout(root);
// Convert to Cartesian coordinates
root.descendants().forEach(d => {
// Convert from polar to Cartesian coordinates
const angle = (d.x - 90) / 180 * Math.PI;
d.x = d.y * Math.cos(angle);
d.y = d.y * Math.sin(angle);
});
// Create links // Create links
const links = g.selectAll('.link') const links = g.selectAll('.link')
@@ -360,10 +376,10 @@
.append('path') .append('path')
.attr('class', 'link') .attr('class', 'link')
.attr('d', d => { .attr('d', d => {
return `M${d.source.y},${d.source.x} return `M${d.source.x},${d.source.y}
C${(d.source.y + d.target.y) / 2},${d.source.x} C${(d.source.x + d.target.x) / 2},${(d.source.y + d.target.y) / 2}
${(d.source.y + d.target.y) / 2},${d.target.x} ${(d.source.x + d.target.x) / 2},${(d.source.y + d.target.y) / 2}
${d.target.y},${d.target.x}`; ${d.target.x},${d.target.y}`;
}); });
// Create nodes // Create nodes
@@ -375,7 +391,7 @@
const categoryClass = getNodeCategory(d.data.name, rootCategories); const categoryClass = getNodeCategory(d.data.name, rootCategories);
return `node ${categoryClass} ${d.data.id === selectedNode ? 'node--selected' : ''}`; return `node ${categoryClass} ${d.data.id === selectedNode ? 'node--selected' : ''}`;
}) })
.attr('transform', d => `translate(${d.y},${d.x})`) .attr('transform', d => `translate(${d.x},${d.y})`)
.on('click', (event, d) => selectNode(d.data.id, d.data.name)) .on('click', (event, d) => selectNode(d.data.id, d.data.name))
.on('mouseover', function(event, d) { .on('mouseover', function(event, d) {
tooltip.transition() tooltip.transition()

35
website/test_app.py Normal file
View File

@@ -0,0 +1,35 @@
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return """
<!DOCTYPE html>
<html>
<head>
<title>Test Seite</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }
.container { max-width: 800px; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 5px; }
h1 { color: #333; }
</style>
</head>
<body>
<div class="container">
<h1>Test Seite funktioniert!</h1>
<p>Wenn Sie diese Seite sehen können, funktioniert der grundlegende Flask-Server korrekt.</p>
<p>Server-Status:</p>
<ul>
<li>Flask läuft auf Port 5000</li>
<li>Keine Datenbankverbindung erforderlich</li>
<li>Keine Templates erforderlich</li>
</ul>
<p>Versuchen Sie, diese URL in verschiedenen Browsern zu öffnen.</p>
</div>
</body>
</html>
"""
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)