diff --git a/Dockerfile b/Dockerfile index 5780a0b..2b0a952 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,27 @@ -FROM python:3.9-slim-buster +FROM python:3.11-slim WORKDIR /app -COPY requirements.txt requirements.txt -RUN pip install -r requirements.txt +# System dependencies +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"] \ No newline at end of file +# Copy application files +COPY website/ ./website/ +COPY requirements.txt . + +EXPOSE 6000 + +# Verify installations +RUN pip list + +CMD ["python", "website/app.py"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index c2faf8f..0d82d19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,16 @@ -version: "3.9" +version: '3.8' + services: web: - build: . + build: + context: . + dockerfile: Dockerfile ports: - - "5000:5000" + - "6000:6000" + volumes: + - ./website:/app/website + environment: + - FLASK_ENV=development + - FLASK_DEBUG=1 + command: python website/app.py restart: always \ No newline at end of file diff --git a/instance/mindmap.db b/instance/mindmap.db new file mode 100644 index 0000000..907f5c3 Binary files /dev/null and b/instance/mindmap.db differ diff --git a/requirements.txt b/requirements.txt index dda7386..5963cc4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -flask -flask-login -flask-wtf -email-validator -python-dotenv -flask-sqlalchemy \ No newline at end of file +Flask +Flask-Login +Flask-SQLAlchemy +Werkzeug +SQLAlchemy +email_validator \ No newline at end of file diff --git a/start-flask-server.py b/start-flask-server.py new file mode 100644 index 0000000..a0f47c8 --- /dev/null +++ b/start-flask-server.py @@ -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) \ No newline at end of file diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..09409b2 --- /dev/null +++ b/start.sh @@ -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 \ No newline at end of file diff --git a/start_server.bat b/start_server.bat new file mode 100644 index 0000000..f8c149e --- /dev/null +++ b/start_server.bat @@ -0,0 +1,5 @@ +@echo off +cd website +echo Starting Flask server on http://127.0.0.1:5000 +python run.py +pause \ No newline at end of file diff --git a/test_server.py b/test_server.py new file mode 100644 index 0000000..8414ef2 --- /dev/null +++ b/test_server.py @@ -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() \ No newline at end of file diff --git a/website/__pycache__/app.cpython-311.pyc b/website/__pycache__/app.cpython-311.pyc deleted file mode 100644 index edb7455..0000000 Binary files a/website/__pycache__/app.cpython-311.pyc and /dev/null differ diff --git a/website/__pycache__/app.cpython-313.pyc b/website/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000..459cb20 Binary files /dev/null and b/website/__pycache__/app.cpython-313.pyc differ diff --git a/website/__pycache__/init_db.cpython-311.pyc b/website/__pycache__/init_db.cpython-311.pyc deleted file mode 100644 index 5cedb65..0000000 Binary files a/website/__pycache__/init_db.cpython-311.pyc and /dev/null differ diff --git a/website/__pycache__/init_db.cpython-313.pyc b/website/__pycache__/init_db.cpython-313.pyc new file mode 100644 index 0000000..3803438 Binary files /dev/null and b/website/__pycache__/init_db.cpython-313.pyc differ diff --git a/website/app.py b/website/app.py index 92c3370..8a68fb8 100644 --- a/website/app.py +++ b/website/app.py @@ -6,15 +6,231 @@ from flask_sqlalchemy import SQLAlchemy from werkzeug.security import generate_password_hash, check_password_hash import json -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 = SQLAlchemy(app) -login_manager = LoginManager(app) +db = SQLAlchemy() +login_manager = LoginManager() 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/', 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/', 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 class User(UserMixin, db.Model): 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) ) -@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/', 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/', 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/', 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__': - with app.app_context(): - # Make sure tables exist - db.create_all() - app.run(host="0.0.0.0", debug=True) \ No newline at end of file + app = create_app() + app.run(host="0.0.0.0", port=5000, debug=True) \ No newline at end of file diff --git a/website/init_db.py b/website/init_db.py index c5d930a..aa75353 100644 --- a/website/init_db.py +++ b/website/init_db.py @@ -1,88 +1,144 @@ -from app import app, db, User, MindMapNode +import os +import sys +from pathlib import Path +import shutil -def init_database(): - """Initialize the database with admin user and mindmap structure.""" - with app.app_context(): - # Create all tables - db.create_all() - - # 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.") +# Pfade zu möglichen Datenbankdateien +db_paths = [ + Path("instance/mindmap.db"), + Path("mindmap.db"), + Path("website/instance/mindmap.db"), + Path("website/mindmap.db") +] -if __name__ == "__main__": - init_database() - print("You can now run the application with 'python app.py'") - print("Login with:") - print(" Admin: username=admin, password=admin123") - print(" User: username=test, password=test123") \ No newline at end of file +# Lösche bestehende Datenbankdateien +for db_path in db_paths: + if db_path.exists(): + try: + print(f"Lösche Datenbank: {db_path}") + 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") \ No newline at end of file diff --git a/website/instance/mindmap.db b/website/instance/mindmap.db index 976a308..1db9c4d 100644 Binary files a/website/instance/mindmap.db and b/website/instance/mindmap.db differ diff --git a/website/run.py b/website/run.py index d03cb9c..986fff9 100644 --- a/website/run.py +++ b/website/run.py @@ -1,11 +1,20 @@ #!/usr/bin/env python3 import os -from init_db import init_database -from app import app +import sys +import logging +from app import create_app + +# Configure logging +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger(__name__) + +app = create_app() if __name__ == "__main__": - # Initialize the database first - init_database() - - # Run the Flask application - app.run(host="0.0.0.0", debug=True) \ No newline at end of file + logger.info("Starting Flask server on http://127.0.0.1:5000") + try: + # Use threaded=True for better request handling + app.run(host="127.0.0.1", port=5000, debug=True, use_reloader=False, threaded=True) + except Exception as e: + logger.error(f"Error starting Flask server: {e}") + sys.exit(1) \ No newline at end of file diff --git a/website/templates/index.html b/website/templates/index.html index f4f66a9..55e5b10 100644 --- a/website/templates/index.html +++ b/website/templates/index.html @@ -8,7 +8,7 @@
- Starte die Mindmap + Zum Netzwerk {% if not current_user.is_authenticated %} @@ -20,19 +20,16 @@
-
🧠

Visualisiere Wissen

Erkenne Zusammenhänge zwischen verschiedenen Wissensgebieten durch intuitive Mindmaps.

-
💡

Teile Gedanken

Füge deine eigenen Gedanken zu bestehenden Themen hinzu und bereichere die Community.

-
🔄

Interaktive Vernetzung

Beteilige dich an Diskussionen und sieh wie sich Ideen gemeinsam entwickeln.

diff --git a/website/templates/mindmap.html b/website/templates/mindmap.html index c36dc69..5c27249 100644 --- a/website/templates/mindmap.html +++ b/website/templates/mindmap.html @@ -99,6 +99,13 @@ .node:hover circle { 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; + } {% endblock %} @@ -346,12 +353,21 @@ // Create hierarchical layout const root = d3.hierarchy(data); - // Create tree layout - const treeLayout = d3.tree() - .size([height - 100, width - 200]) - .nodeSize([80, 200]); + // Create radial layout instead of tree for all-direction branches + const radius = Math.min(width, height) / 2 - 100; - 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 const links = g.selectAll('.link') @@ -360,10 +376,10 @@ .append('path') .attr('class', 'link') .attr('d', d => { - return `M${d.source.y},${d.source.x} - C${(d.source.y + d.target.y) / 2},${d.source.x} - ${(d.source.y + d.target.y) / 2},${d.target.x} - ${d.target.y},${d.target.x}`; + return `M${d.source.x},${d.source.y} + C${(d.source.x + d.target.x) / 2},${(d.source.y + d.target.y) / 2} + ${(d.source.x + d.target.x) / 2},${(d.source.y + d.target.y) / 2} + ${d.target.x},${d.target.y}`; }); // Create nodes @@ -375,7 +391,7 @@ const categoryClass = getNodeCategory(d.data.name, rootCategories); 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('mouseover', function(event, d) { tooltip.transition() diff --git a/website/test_app.py b/website/test_app.py new file mode 100644 index 0000000..0f9cdc0 --- /dev/null +++ b/website/test_app.py @@ -0,0 +1,35 @@ +from flask import Flask + +app = Flask(__name__) + +@app.route('/') +def hello(): + return """ + + + + Test Seite + + + +
+

Test Seite funktioniert!

+

Wenn Sie diese Seite sehen können, funktioniert der grundlegende Flask-Server korrekt.

+

Server-Status:

+
    +
  • Flask läuft auf Port 5000
  • +
  • Keine Datenbankverbindung erforderlich
  • +
  • Keine Templates erforderlich
  • +
+

Versuchen Sie, diese URL in verschiedenen Browsern zu öffnen.

+
+ + + """ + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000, debug=True) \ No newline at end of file