Compare commits
2 Commits
013bf76446
...
till-v2
| Author | SHA1 | Date | |
|---|---|---|---|
| b8ad3aea13 | |||
| edf3049e42 |
10
Dockerfile
10
Dockerfile
@@ -1,10 +0,0 @@
|
|||||||
FROM python:3.9-slim-buster
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY requirements.txt requirements.txt
|
|
||||||
RUN pip install -r requirements.txt
|
|
||||||
|
|
||||||
COPY website .
|
|
||||||
|
|
||||||
CMD ["python", "app.py"]
|
|
||||||
180
README.md
180
README.md
@@ -1,94 +1,134 @@
|
|||||||
# MindMap Wissensnetzwerk
|
# MindMapProjekt - Roadmap
|
||||||
|
|
||||||
Eine interaktive Plattform zum Visualisieren, Erforschen und Teilen von Wissen mit integriertem ChatGPT-Assistenten.
|
## Projektübersicht
|
||||||
|
Das MindMapProjekt ist eine interaktive Plattform zum Visualisieren, Erforschen und Teilen von Wissen. Das Projekt wird umfassend überarbeitet, um ein modernes, benutzerfreundliches Design und erweiterte Funktionalitäten zu bieten.
|
||||||
|
|
||||||
## Features
|
## Technischer Stack
|
||||||
|
- **Backend**: Python/Flask
|
||||||
|
- **Frontend**:
|
||||||
|
- Tailwind CSS für moderne UI
|
||||||
|
- SVG-Bibliotheken für Visualisierungen (D3.js)
|
||||||
|
- JavaScript/Alpine.js für interaktive Komponenten
|
||||||
|
- **Datenbank**: SQLite mit SQLAlchemy
|
||||||
|
- **KI-Integration**: OpenAI API für intelligente Assistenz
|
||||||
|
|
||||||
- Interaktive Mindmap zur Visualisierung von Wissensverbindungen
|
## Installation und Verwendung
|
||||||
- Gedanken mit verschiedenen Beziehungstypen verknüpfen
|
|
||||||
- Suchfunktion für Gedanken und Verbindungen
|
|
||||||
- Bewertungssystem für Gedanken
|
|
||||||
- Dark/Light Mode
|
|
||||||
- **Integrierter KI-Assistent** mit OpenAI GPT-Integration
|
|
||||||
|
|
||||||
## Installation
|
### Installation
|
||||||
|
1. Repository klonen
|
||||||
|
2. Virtuelle Umgebung erstellen: `python -m venv venv`
|
||||||
|
3. Virtuelle Umgebung aktivieren:
|
||||||
|
- Windows: `venv\Scripts\activate`
|
||||||
|
- Unix/MacOS: `source venv/bin/activate`
|
||||||
|
4. Abhängigkeiten installieren: `pip install -r requirements.txt`
|
||||||
|
5. Datenbank initialisieren: `python TOOLS.py db:rebuild`
|
||||||
|
6. Admin-Benutzer erstellen: `python TOOLS.py user:admin`
|
||||||
|
7. Server starten: `python TOOLS.py server:run`
|
||||||
|
|
||||||
### Einfache Installation
|
### Standardbenutzer
|
||||||
|
- **Admin-Benutzer**: Username: `admin` / Passwort: `admin`
|
||||||
|
- **Testbenutzer**: Username: `user` / Passwort: `user`
|
||||||
|
|
||||||
Führe im übergeordneten Verzeichnis folgendes aus:
|
### Verwaltungswerkzeuge mit TOOLS.py
|
||||||
|
Das Projekt enthält ein zentrales Verwaltungsskript `TOOLS.py`, das verschiedene Hilfsfunktionen bietet:
|
||||||
|
|
||||||
```
|
#### Datenbankverwaltung
|
||||||
python setup.py
|
- `python TOOLS.py db:fix` - Reparieren der Datenbankstruktur
|
||||||
```
|
- `python TOOLS.py db:rebuild` - Datenbank neu aufbauen (löscht alle Daten!)
|
||||||
|
- `python TOOLS.py db:test` - Datenbankverbindung und Modelle testen
|
||||||
|
- `python TOOLS.py db:stats` - Datenbankstatistiken anzeigen
|
||||||
|
|
||||||
Dies erstellt eine virtuelle Umgebung, installiert alle Abhängigkeiten und erstellt die CSS-Dateien mit Tailwind.
|
#### Benutzerverwaltung
|
||||||
|
- `python TOOLS.py user:list` - Alle Benutzer anzeigen
|
||||||
|
- `python TOOLS.py user:create -u USERNAME -e EMAIL -p PASSWORD [-a]` - Neuen Benutzer erstellen
|
||||||
|
- `python TOOLS.py user:admin` - Admin-Benutzer erstellen (admin/admin)
|
||||||
|
- `python TOOLS.py user:reset-pw -u USERNAME -p NEWPASSWORD` - Benutzerpasswort zurücksetzen
|
||||||
|
- `python TOOLS.py user:delete -u USERNAME` - Benutzer löschen
|
||||||
|
|
||||||
### Manuelle Installation
|
#### Serververwaltung
|
||||||
|
- `python TOOLS.py server:run [--host HOST] [--port PORT] [--no-debug]` - Entwicklungsserver starten
|
||||||
|
|
||||||
1. Repository klonen:
|
Für detaillierte Hilfe: `python TOOLS.py -h`
|
||||||
```
|
|
||||||
git clone <repository-url>
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Python-Abhängigkeiten installieren:
|
## Roadmap der Überarbeitung
|
||||||
```
|
|
||||||
cd website
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Environment-Variablen konfigurieren:
|
### Phase 1: Grundlegende Infrastruktur ✅
|
||||||
```
|
- [x] Bestandsaufnahme des aktuellen Projekts
|
||||||
cp example.env .env
|
- [x] Erstellung der Roadmap
|
||||||
```
|
- [x] Aktualisierung der Abhängigkeiten
|
||||||
Bearbeite die `.env`-Datei und füge deinen OpenAI API-Schlüssel ein.
|
- [x] Integration von Tailwind CSS
|
||||||
|
- [x] Einrichtung der SVG-Bibliotheken (D3.js)
|
||||||
|
- [x] Favicon erstellen
|
||||||
|
- [x] Setup-Skript für einfache Installation
|
||||||
|
|
||||||
4. CSS mit Tailwind erstellen:
|
### Phase 2: Design-Überarbeitung 🔄
|
||||||
```
|
- [x] Implementierung des Dark Mode
|
||||||
python build_css.py
|
- [x] Erstellung eines modernen, minimalistischen UI mit Tech-Ästhetik
|
||||||
```
|
- [x] Responsive Design für alle Geräte
|
||||||
|
- [ ] Gestaltung der Landing Page mit großer Typografie
|
||||||
|
|
||||||
5. Datenbank initialisieren:
|
### Phase 3: Mindmap-Funktionalitäten 🔄
|
||||||
```
|
- [x] Verbesserte Visualisierung mit SVG und D3.js
|
||||||
python init_db.py
|
- [x] Implementierung der Mouseover-Funktion
|
||||||
```
|
- [x] Entwicklung der Suchfunktion für Knoten
|
||||||
|
- [ ] Tagging-System für Inhalte
|
||||||
|
- [ ] Quellenmanagement und -verlinkung
|
||||||
|
- [ ] Upload-Funktionalität an Knotenpunkten
|
||||||
|
|
||||||
6. Anwendung starten:
|
### Phase 4: Kernseitenentwicklung
|
||||||
```
|
- [ ] Überarbeitung der Startseite mit neuen Features
|
||||||
python run.py
|
- [ ] Entwicklung der "Wer sind wir?"-Seite
|
||||||
```
|
- [ ] Implementierung von Impressum und Datenschutzerklärung
|
||||||
|
- [ ] Erstellung der Kontaktseite mit FAQs
|
||||||
|
- [ ] Überarbeitung des Benutzerprofilbereichs
|
||||||
|
|
||||||
## Entwicklung
|
### Phase 5: Community-Features
|
||||||
|
- [ ] Entwicklung des Autorenbereichs
|
||||||
|
- [ ] Implementierung von Community-Bereichen für Themenbereiche
|
||||||
|
- [ ] Verbesserter Kommentarbereich
|
||||||
|
- [ ] Benutzerrechtemanagement
|
||||||
|
|
||||||
Für die Entwicklung mit automatischem CSS-Reload:
|
### Phase 6: KI-Integration
|
||||||
|
- [ ] Implementierung des Frage-Antwort-Systems
|
||||||
|
- [ ] KI-generierte Themeneinleitungen
|
||||||
|
- [ ] Intelligente Suchunterstützung
|
||||||
|
- [ ] Geführte Pfade durch Themenbereiche
|
||||||
|
- [ ] Vorgeschlagene Chat-Möglichkeiten
|
||||||
|
|
||||||
```
|
### Phase 7: Benutzerprofilfunktionen
|
||||||
python dev.py
|
- [ ] Speichern von Thematiken
|
||||||
```
|
- [ ] Persönliche Mindmap/Pinboard
|
||||||
|
- [ ] Beitragsmanagement
|
||||||
|
- [ ] Benutzerstatistiken und -aktivitäten
|
||||||
|
|
||||||
Dieser Befehl startet sowohl den Flask-Server als auch den Tailwind CSS-Watcher, der CSS bei Änderungen automatisch neu generiert.
|
### Phase 8: Testing und Optimierung
|
||||||
|
- [ ] Umfassende Tests aller Funktionen
|
||||||
|
- [ ] Performance-Optimierung
|
||||||
|
- [ ] SEO-Implementierung
|
||||||
|
- [ ] Barrierefreiheit prüfen und verbessern
|
||||||
|
|
||||||
## Verwendung des KI-Assistenten
|
### Phase 9: Dokumentation und Einführung
|
||||||
|
- [ ] Erstellung von Benutzeranleitungen
|
||||||
|
- [ ] Entwicklerdokumentation
|
||||||
|
- [ ] Administratorenhandbuch
|
||||||
|
- [ ] Guided Tour für neue Benutzer
|
||||||
|
|
||||||
Der KI-Assistent ist über folgende Wege zugänglich:
|
## Aktueller Status
|
||||||
|
- **Phase 1**: ✅ Abgeschlossen
|
||||||
|
- **Phase 2**: 🔄 In Bearbeitung (75% abgeschlossen)
|
||||||
|
- **Phase 3**: 🔄 In Bearbeitung (50% abgeschlossen)
|
||||||
|
|
||||||
1. **Schwebende Schaltfläche**: In der unteren rechten Ecke der Webseite ist eine Roboter-Schaltfläche, die den Assistenten öffnet.
|
## Aktuelle Fortschritte
|
||||||
2. **Navigation**: In der Hauptnavigation gibt es ebenfalls eine Schaltfläche mit Roboter-Symbol.
|
- Grundlegende UI modernisiert mit Tailwind CSS und Dark Mode
|
||||||
3. **Startseite**: Im "KI-Assistent"-Abschnitt auf der Startseite gibt es einen "KI-Chat starten"-Button.
|
- Neues Favicon für bessere visuelle Identität erstellt
|
||||||
|
- Setup-Prozess vereinfacht mit einem Shell-Skript
|
||||||
|
- Mindmap-Visualisierung komplett überarbeitet mit D3.js für eine interaktivere Erfahrung
|
||||||
|
- Responsive Design für optimale Darstellung auf allen Geräten
|
||||||
|
|
||||||
Der Assistent kann bei folgenden Aufgaben helfen:
|
## Nächste Schritte
|
||||||
|
- Fertigstellung der Landing Page
|
||||||
|
- Erstellung der "Wer sind wir?"-Seite
|
||||||
|
- Implementierung des Tagging-Systems für Gedanken
|
||||||
|
- Verbesserung der Gedankenansicht im Mindmap-Bereich
|
||||||
|
|
||||||
- Erklärung von Themen und Konzepten
|
*Zuletzt aktualisiert: 01.06.2024*
|
||||||
- Suche nach Verbindungen zwischen Gedanken
|
|
||||||
- Beantwortung von Fragen zur Plattform
|
|
||||||
- Vorschläge für neue Gedankenverbindungen
|
|
||||||
|
|
||||||
## Technologie-Stack
|
|
||||||
|
|
||||||
- **Backend**: Flask, SQLAlchemy
|
|
||||||
- **Frontend**: HTML, CSS, JavaScript, Tailwind CSS (ohne npm), Alpine.js
|
|
||||||
- **KI**: OpenAI GPT API
|
|
||||||
- **Datenbank**: SQLite (Standard), kann auf andere Datenbanken umgestellt werden
|
|
||||||
|
|
||||||
## Konfiguration
|
|
||||||
|
|
||||||
Die Anwendung kann über Umgebungsvariablen konfiguriert werden. Siehe `example.env` für verfügbare Optionen.
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1145,10 +1145,24 @@ def my_account():
|
|||||||
@app.route('/static/network-bg.jpg')
|
@app.route('/static/network-bg.jpg')
|
||||||
@app.route('/static/network-bg.svg')
|
@app.route('/static/network-bg.svg')
|
||||||
def dummy_network_bg():
|
def dummy_network_bg():
|
||||||
"""Leere Antwort für die nicht mehr verwendeten Netzwerk-Hintergrundbilder."""
|
"""Stellt einen Fallback für alte Netzwerk-Hintergrund-Anfragen bereit."""
|
||||||
return '', 200
|
return redirect(url_for('static', filename='img/backgrounds/network-bg.jpg'))
|
||||||
|
|
||||||
|
@app.route('/static/css/src/cybernetwork-bg.css')
|
||||||
|
def serve_cybernetwork_css():
|
||||||
|
"""Stellt das CSS für den cybertechnischen Netzwerk-Hintergrund bereit."""
|
||||||
|
return app.send_static_file('css/src/cybernetwork-bg.css')
|
||||||
|
|
||||||
|
@app.route('/static/js/modules/cyber-network.js')
|
||||||
|
def serve_cybernetwork_js():
|
||||||
|
"""Stellt das JavaScript-Modul für den cybertechnischen Netzwerk-Hintergrund bereit."""
|
||||||
|
return app.send_static_file('js/modules/cyber-network.js')
|
||||||
|
|
||||||
|
@app.route('/static/js/modules/cyber-network-init.js')
|
||||||
|
def serve_cybernetwork_init_js():
|
||||||
|
"""Stellt das Initialisierungs-JavaScript für den cybertechnischen Netzwerk-Hintergrund bereit."""
|
||||||
|
return app.send_static_file('js/modules/cyber-network-init.js')
|
||||||
|
|
||||||
# Route zum expliziten Neu-Laden der Umgebungsvariablen
|
|
||||||
@app.route('/admin/reload-env', methods=['POST'])
|
@app.route('/admin/reload-env', methods=['POST'])
|
||||||
@admin_required
|
@admin_required
|
||||||
def reload_env():
|
def reload_env():
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
@echo off
|
|
||||||
echo Copying network image to website/static/network-bg.jpg...
|
|
||||||
|
|
||||||
if not exist "website\static" (
|
|
||||||
echo Error: website/static directory does not exist.
|
|
||||||
echo Make sure you are running this script from the main project directory.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%~1"=="" (
|
|
||||||
echo Usage: copy-network-image.bat [path_to_image]
|
|
||||||
echo Example: copy-network-image.bat d2efd014-1325-471f-b9a7-90d025eb81d6.png
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if not exist "%~1" (
|
|
||||||
echo Error: The specified image file "%~1" does not exist.
|
|
||||||
pause
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
copy /Y "%~1" "website\static\network-bg.jpg" > nul
|
|
||||||
|
|
||||||
if %errorlevel% equ 0 (
|
|
||||||
echo Success! The image has been copied to website/static/network-bg.jpg
|
|
||||||
echo Please restart the Flask server to see the changes.
|
|
||||||
) else (
|
|
||||||
echo Error: Failed to copy the image.
|
|
||||||
)
|
|
||||||
|
|
||||||
pause
|
|
||||||
86
deploy.py
86
deploy.py
@@ -1,86 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import shutil
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Deploy the website on a server"""
|
|
||||||
print("Deploying the website on the server...")
|
|
||||||
|
|
||||||
# Get the directory where deploy.py is located (project root)
|
|
||||||
project_root = Path(__file__).resolve().parent
|
|
||||||
website_dir = project_root / "website"
|
|
||||||
|
|
||||||
# Check if virtual environment exists, create if not
|
|
||||||
venv_dir = project_root / "venv"
|
|
||||||
if not venv_dir.exists():
|
|
||||||
print("Creating virtual environment...")
|
|
||||||
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
|
|
||||||
|
|
||||||
# Determine Python and pip paths based on OS
|
|
||||||
if os.name == 'nt': # Windows
|
|
||||||
python = venv_dir / "Scripts" / "python"
|
|
||||||
pip = venv_dir / "Scripts" / "pip"
|
|
||||||
else: # Unix-like
|
|
||||||
python = venv_dir / "bin" / "python"
|
|
||||||
pip = venv_dir / "bin" / "pip"
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
print("Installing dependencies...")
|
|
||||||
subprocess.run([str(pip), "install", "-r", str(website_dir / "requirements.txt")], check=True)
|
|
||||||
subprocess.run([str(pip), "install", "gunicorn"], check=True)
|
|
||||||
|
|
||||||
# Build CSS
|
|
||||||
print("Building CSS with Tailwind...")
|
|
||||||
subprocess.run([str(python), str(website_dir / "build_css.py")], check=True)
|
|
||||||
|
|
||||||
# Create a systemd service file
|
|
||||||
service_file = """[Unit]
|
|
||||||
Description=MindMap Wissensnetzwerk
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
User=www-data
|
|
||||||
WorkingDirectory={website_dir}
|
|
||||||
Environment="PATH={venv_bin}"
|
|
||||||
ExecStart={gunicorn} --workers 3 --bind 0.0.0.0:5000 --log-level info 'run:app'
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
""".format(
|
|
||||||
website_dir=website_dir,
|
|
||||||
venv_bin=venv_dir / "bin",
|
|
||||||
gunicorn=venv_dir / "bin" / "gunicorn"
|
|
||||||
)
|
|
||||||
|
|
||||||
service_path = project_root / "mindmap.service"
|
|
||||||
with open(service_path, 'w') as f:
|
|
||||||
f.write(service_file)
|
|
||||||
|
|
||||||
print(f"""
|
|
||||||
Deployment files created!
|
|
||||||
|
|
||||||
To install the service on a Linux server:
|
|
||||||
1. Copy the systemd service file:
|
|
||||||
sudo cp {service_path} /etc/systemd/system/
|
|
||||||
|
|
||||||
2. Reload systemd:
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
|
|
||||||
3. Enable and start the service:
|
|
||||||
sudo systemctl enable mindmap.service
|
|
||||||
sudo systemctl start mindmap.service
|
|
||||||
|
|
||||||
4. Check service status:
|
|
||||||
sudo systemctl status mindmap.service
|
|
||||||
|
|
||||||
Alternatively, you can run the application with gunicorn manually:
|
|
||||||
cd {website_dir}
|
|
||||||
{venv_dir}/bin/gunicorn --workers 3 --bind 0.0.0.0:5000 'run:app'
|
|
||||||
""")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
60
deploy.sh
60
deploy.sh
@@ -1,60 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Farben für Ausgaben
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
echo -e "${GREEN}==== MindMap Projekt Server Deployment ====${NC}"
|
|
||||||
|
|
||||||
# Python-Umgebung erstellen
|
|
||||||
echo -e "${BLUE}Erstelle Python-Umgebung...${NC}"
|
|
||||||
python3 -m venv venv
|
|
||||||
source venv/bin/activate
|
|
||||||
|
|
||||||
# Python-Abhängigkeiten installieren
|
|
||||||
echo -e "${BLUE}Installiere Python-Abhängigkeiten...${NC}"
|
|
||||||
pip install -r website/requirements.txt
|
|
||||||
pip install gunicorn
|
|
||||||
|
|
||||||
# Tailwind CSS kompilieren
|
|
||||||
echo -e "${BLUE}Kompiliere Tailwind CSS...${NC}"
|
|
||||||
cd website
|
|
||||||
python build_css.py
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# Datenbank initialisieren, falls noch nicht vorhanden
|
|
||||||
echo -e "${BLUE}Initialisiere die Datenbank, falls nötig...${NC}"
|
|
||||||
cd website
|
|
||||||
python init_db.py
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# Systemd Service erstellen
|
|
||||||
echo -e "${BLUE}Erstelle Systemd Service...${NC}"
|
|
||||||
SERVICE_FILE="[Unit]
|
|
||||||
Description=MindMap Wissensnetzwerk
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
User=$(whoami)
|
|
||||||
WorkingDirectory=$(pwd)/website
|
|
||||||
Environment=\"PATH=$(pwd)/venv/bin\"
|
|
||||||
ExecStart=$(pwd)/venv/bin/gunicorn --workers 3 --bind 0.0.0.0:5000 --log-level info 'run:app'
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target"
|
|
||||||
|
|
||||||
echo "$SERVICE_FILE" > mindmap.service
|
|
||||||
|
|
||||||
echo -e "${GREEN}==== Deployment abgeschlossen ====${NC}"
|
|
||||||
echo -e "${BLUE}Um den Service zu installieren, führe folgende Befehle aus:${NC}"
|
|
||||||
echo -e "sudo cp mindmap.service /etc/systemd/system/"
|
|
||||||
echo -e "sudo systemctl daemon-reload"
|
|
||||||
echo -e "sudo systemctl enable mindmap.service"
|
|
||||||
echo -e "sudo systemctl start mindmap.service"
|
|
||||||
echo -e ""
|
|
||||||
echo -e "${BLUE}Alternativ kannst du den Server manuell starten:${NC}"
|
|
||||||
echo -e "cd website"
|
|
||||||
echo -e "../venv/bin/gunicorn --workers 3 --bind 0.0.0.0:5000 'run:app'"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
version: "3.9"
|
|
||||||
services:
|
|
||||||
web:
|
|
||||||
build: .
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
restart: always
|
|
||||||
53
setup.py
53
setup.py
@@ -1,53 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Set up the project from the parent directory"""
|
|
||||||
print("Setting up the project...")
|
|
||||||
|
|
||||||
# Get the directory where setup.py is located (project root)
|
|
||||||
project_root = Path(__file__).resolve().parent
|
|
||||||
website_dir = project_root / "website"
|
|
||||||
|
|
||||||
# Check if virtual environment exists, create if not
|
|
||||||
venv_dir = project_root / "venv"
|
|
||||||
if not venv_dir.exists():
|
|
||||||
print("Creating virtual environment...")
|
|
||||||
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
|
|
||||||
|
|
||||||
# Determine pip path based on OS
|
|
||||||
if os.name == 'nt': # Windows
|
|
||||||
pip = venv_dir / "Scripts" / "pip"
|
|
||||||
else: # Unix-like
|
|
||||||
pip = venv_dir / "bin" / "pip"
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
print("Installing dependencies...")
|
|
||||||
subprocess.run([str(pip), "install", "-r", str(website_dir / "requirements.txt")], check=True)
|
|
||||||
|
|
||||||
# Build CSS
|
|
||||||
print("Building CSS with Tailwind...")
|
|
||||||
if os.name == 'nt': # Windows
|
|
||||||
python = venv_dir / "Scripts" / "python"
|
|
||||||
else: # Unix-like
|
|
||||||
python = venv_dir / "bin" / "python"
|
|
||||||
|
|
||||||
subprocess.run([str(python), str(website_dir / "build_css.py")], check=True)
|
|
||||||
|
|
||||||
print("""
|
|
||||||
Setup completed successfully!
|
|
||||||
|
|
||||||
To run the development server:
|
|
||||||
1. Activate the virtual environment:
|
|
||||||
- Windows: .\\venv\\Scripts\\activate
|
|
||||||
- Unix/MacOS: source venv/bin/activate
|
|
||||||
2. Run the Flask application:
|
|
||||||
- cd website
|
|
||||||
- python run.py
|
|
||||||
""")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
125
static/css/src/cybernetwork-bg.css
Normal file
125
static/css/src/cybernetwork-bg.css
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
/* Cybertechnisches Netzwerk Hintergrund-Overlay */
|
||||||
|
.cyber-network-bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cyber-network-bg::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(125deg,
|
||||||
|
rgba(14, 14, 22, 0.95) 0%,
|
||||||
|
rgba(30, 30, 46, 0.98) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-grid {
|
||||||
|
position: absolute;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
top: -50%;
|
||||||
|
left: -50%;
|
||||||
|
background-size: 40px 40px;
|
||||||
|
background-image:
|
||||||
|
linear-gradient(to right, rgba(108, 93, 211, 0.05) 1px, transparent 1px),
|
||||||
|
linear-gradient(to bottom, rgba(108, 93, 211, 0.05) 1px, transparent 1px);
|
||||||
|
transform: perspective(500px) rotateX(60deg);
|
||||||
|
animation: grid-move 20s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node {
|
||||||
|
position: absolute;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
background: rgba(76, 223, 255, 0.8);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 10px rgba(76, 223, 255, 0.6);
|
||||||
|
filter: blur(1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection {
|
||||||
|
position: absolute;
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
rgba(76, 223, 255, 0.2) 0%,
|
||||||
|
rgba(108, 93, 211, 0.3) 50%,
|
||||||
|
rgba(76, 223, 255, 0.2) 100%);
|
||||||
|
transform-origin: left center;
|
||||||
|
animation: pulse 4s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-packet {
|
||||||
|
position: absolute;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(118, 69, 217, 0.8);
|
||||||
|
filter: blur(1px);
|
||||||
|
animation: travel var(--travel-time, 6s) linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glow-overlay {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at 50% 40%,
|
||||||
|
rgba(76, 223, 255, 0.03) 0%,
|
||||||
|
rgba(108, 93, 211, 0.03) 45%,
|
||||||
|
transparent 70%
|
||||||
|
);
|
||||||
|
opacity: 0.8;
|
||||||
|
animation: pulse-glow 8s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@keyframes grid-move {
|
||||||
|
0% {
|
||||||
|
transform: perspective(500px) rotateX(60deg) translateY(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: perspective(500px) rotateX(60deg) translateY(40px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes travel {
|
||||||
|
0% {
|
||||||
|
transform: translateX(0) translateY(0);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(var(--travel-x, 100px)) translateY(var(--travel-y, 100px));
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-glow {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1434,11 +1434,16 @@ html, body {
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
background: linear-gradient(135deg, var(--background-start), var(--background-end));
|
background: linear-gradient(135deg, var(--background-start), var(--background-end));
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sticky navbar */
|
/* Sticky navbar */
|
||||||
.navbar.sticky-top {
|
.navbar.sticky-top {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 1000;
|
z-index: 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Importiere das Cyber-Network CSS */
|
||||||
|
@import url('/static/css/src/cybernetwork-bg.css');
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
95
static/js/modules/cyber-network-init.js
Normal file
95
static/js/modules/cyber-network-init.js
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* Initialisierungsmodul für den CyberNetwork-Hintergrund
|
||||||
|
* Importiert und startet die Animation
|
||||||
|
*/
|
||||||
|
|
||||||
|
import CyberNetwork from './cyber-network.js';
|
||||||
|
|
||||||
|
// Beim Laden des Dokuments starten
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
console.log('CyberNetwork: Initialisierung gestartet');
|
||||||
|
|
||||||
|
// Prüfen ob das CSS bereits geladen ist, wenn nicht, dann laden
|
||||||
|
if (!document.querySelector('link[href*="cybernetwork-bg.css"]')) {
|
||||||
|
console.log('CyberNetwork: CSS wird geladen');
|
||||||
|
const cyberNetworkCss = document.createElement('link');
|
||||||
|
cyberNetworkCss.rel = 'stylesheet';
|
||||||
|
cyberNetworkCss.href = '/static/css/src/cybernetwork-bg.css';
|
||||||
|
document.head.appendChild(cyberNetworkCss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container-Element für das Netzwerk finden
|
||||||
|
const container = document.getElementById('cyber-background-container');
|
||||||
|
|
||||||
|
if (!container) {
|
||||||
|
console.error('CyberNetwork: Container #cyber-background-container nicht gefunden!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('CyberNetwork: Container gefunden', container);
|
||||||
|
|
||||||
|
// Konfiguration für den Netzwerk-Hintergrund
|
||||||
|
const networkConfig = {
|
||||||
|
container: container,
|
||||||
|
nodeCount: window.innerWidth < 768 ? 15 : 30, // Weniger Nodes auf mobilen Geräten
|
||||||
|
connectionCount: window.innerWidth < 768 ? 25 : 50,
|
||||||
|
packetCount: window.innerWidth < 768 ? 8 : 15,
|
||||||
|
animationSpeed: 1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Netzwerk erstellen und initialisieren
|
||||||
|
const cyberNetwork = new CyberNetwork(networkConfig);
|
||||||
|
cyberNetwork.init();
|
||||||
|
console.log('CyberNetwork: Netzwerk initialisiert');
|
||||||
|
|
||||||
|
// Globale Referenz für Debug-Zwecke
|
||||||
|
window.cyberNetwork = cyberNetwork;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Funktion zum manuellen Initialisieren, falls notwendig
|
||||||
|
export function initCyberNetwork(config = {}) {
|
||||||
|
console.log('CyberNetwork: Manuelle Initialisierung gestartet');
|
||||||
|
|
||||||
|
// CSS laden, falls nicht vorhanden
|
||||||
|
if (!document.querySelector('link[href*="cybernetwork-bg.css"]')) {
|
||||||
|
console.log('CyberNetwork: CSS wird geladen (manuell)');
|
||||||
|
const cyberNetworkCss = document.createElement('link');
|
||||||
|
cyberNetworkCss.rel = 'stylesheet';
|
||||||
|
cyberNetworkCss.href = '/static/css/src/cybernetwork-bg.css';
|
||||||
|
document.head.appendChild(cyberNetworkCss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container-Element für das Netzwerk finden
|
||||||
|
const container = document.getElementById('cyber-background-container');
|
||||||
|
|
||||||
|
if (!container) {
|
||||||
|
console.error('CyberNetwork: Container #cyber-background-container nicht gefunden!');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bestehende Instanz zurücksetzen, falls vorhanden
|
||||||
|
if (window.cyberNetwork) {
|
||||||
|
console.log('CyberNetwork: Bestehende Instanz wird zurückgesetzt');
|
||||||
|
window.cyberNetwork.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Netzwerk mit benutzerdefinierten Optionen erstellen
|
||||||
|
const networkConfig = {
|
||||||
|
container: container,
|
||||||
|
nodeCount: window.innerWidth < 768 ? 15 : 30,
|
||||||
|
connectionCount: window.innerWidth < 768 ? 25 : 50,
|
||||||
|
packetCount: window.innerWidth < 768 ? 8 : 15,
|
||||||
|
animationSpeed: 1.0,
|
||||||
|
...config
|
||||||
|
};
|
||||||
|
|
||||||
|
// Neue Instanz erstellen und initialisieren
|
||||||
|
const cyberNetwork = new CyberNetwork(networkConfig);
|
||||||
|
cyberNetwork.init();
|
||||||
|
console.log('CyberNetwork: Netzwerk manuell initialisiert');
|
||||||
|
|
||||||
|
// Globale Referenz aktualisieren
|
||||||
|
window.cyberNetwork = cyberNetwork;
|
||||||
|
|
||||||
|
return cyberNetwork;
|
||||||
|
}
|
||||||
240
static/js/modules/cyber-network.js
Normal file
240
static/js/modules/cyber-network.js
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
/**
|
||||||
|
* Cyber Network Background Animation
|
||||||
|
* Generiert dynamisch ein animiertes Netzwerk für den Hintergrund
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CyberNetwork {
|
||||||
|
constructor(options = {}) {
|
||||||
|
this.options = {
|
||||||
|
container: options.container || document.body,
|
||||||
|
nodeCount: options.nodeCount || 30,
|
||||||
|
connectionCount: options.connectionCount || 50,
|
||||||
|
packetCount: options.packetCount || 15,
|
||||||
|
animationSpeed: options.animationSpeed || 1.0,
|
||||||
|
...options
|
||||||
|
};
|
||||||
|
|
||||||
|
this.nodes = [];
|
||||||
|
this.connections = [];
|
||||||
|
this.packets = [];
|
||||||
|
this.initialized = false;
|
||||||
|
|
||||||
|
this.containerElement = null;
|
||||||
|
this.networkGridElement = null;
|
||||||
|
this.glowOverlayElement = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
if (this.initialized) return;
|
||||||
|
|
||||||
|
// Container erstellen
|
||||||
|
this.containerElement = document.createElement('div');
|
||||||
|
this.containerElement.className = 'cyber-network-bg';
|
||||||
|
|
||||||
|
// Grid erstellen
|
||||||
|
this.networkGridElement = document.createElement('div');
|
||||||
|
this.networkGridElement.className = 'network-grid';
|
||||||
|
this.containerElement.appendChild(this.networkGridElement);
|
||||||
|
|
||||||
|
// Glow Overlay erstellen
|
||||||
|
this.glowOverlayElement = document.createElement('div');
|
||||||
|
this.glowOverlayElement.className = 'glow-overlay';
|
||||||
|
this.containerElement.appendChild(this.glowOverlayElement);
|
||||||
|
|
||||||
|
// Nodes generieren
|
||||||
|
this.generateNodes();
|
||||||
|
|
||||||
|
// Connections generieren
|
||||||
|
this.generateConnections();
|
||||||
|
|
||||||
|
// Data packets generieren
|
||||||
|
this.generateDataPackets();
|
||||||
|
|
||||||
|
// Container zum DOM hinzufügen
|
||||||
|
if (typeof this.options.container === 'string') {
|
||||||
|
const container = document.querySelector(this.options.container);
|
||||||
|
if (container) {
|
||||||
|
container.appendChild(this.containerElement);
|
||||||
|
} else {
|
||||||
|
document.body.appendChild(this.containerElement);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.options.container.appendChild(this.containerElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
|
||||||
|
// Animation starten
|
||||||
|
window.addEventListener('resize', this.handleResize.bind(this));
|
||||||
|
this.startAnimationCycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
generateNodes() {
|
||||||
|
const containerWidth = window.innerWidth;
|
||||||
|
const containerHeight = window.innerHeight;
|
||||||
|
|
||||||
|
for (let i = 0; i < this.options.nodeCount; i++) {
|
||||||
|
const x = Math.random() * containerWidth;
|
||||||
|
const y = Math.random() * containerHeight;
|
||||||
|
|
||||||
|
const node = document.createElement('div');
|
||||||
|
node.className = 'node';
|
||||||
|
node.style.left = `${x}px`;
|
||||||
|
node.style.top = `${y}px`;
|
||||||
|
|
||||||
|
// Größen-Variation für visuelle Tiefe
|
||||||
|
const size = 2 + Math.random() * 4;
|
||||||
|
node.style.width = `${size}px`;
|
||||||
|
node.style.height = `${size}px`;
|
||||||
|
|
||||||
|
// Speichern der Position für spätere Referenz
|
||||||
|
node._data = { x, y, size };
|
||||||
|
|
||||||
|
this.containerElement.appendChild(node);
|
||||||
|
this.nodes.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generateConnections() {
|
||||||
|
for (let i = 0; i < this.options.connectionCount; i++) {
|
||||||
|
// Zufällige Nodes auswählen
|
||||||
|
const startNodeIndex = Math.floor(Math.random() * this.nodes.length);
|
||||||
|
let endNodeIndex;
|
||||||
|
do {
|
||||||
|
endNodeIndex = Math.floor(Math.random() * this.nodes.length);
|
||||||
|
} while (endNodeIndex === startNodeIndex);
|
||||||
|
|
||||||
|
const startNode = this.nodes[startNodeIndex];
|
||||||
|
const endNode = this.nodes[endNodeIndex];
|
||||||
|
const startData = startNode._data;
|
||||||
|
const endData = endNode._data;
|
||||||
|
|
||||||
|
// Verbindung erstellen
|
||||||
|
const connection = document.createElement('div');
|
||||||
|
connection.className = 'connection';
|
||||||
|
|
||||||
|
// Position und Rotation berechnen
|
||||||
|
const dx = endData.x - startData.x;
|
||||||
|
const dy = endData.y - startData.y;
|
||||||
|
const length = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
const angle = Math.atan2(dy, dx) * (180 / Math.PI);
|
||||||
|
|
||||||
|
connection.style.width = `${length}px`;
|
||||||
|
connection.style.left = `${startData.x}px`;
|
||||||
|
connection.style.top = `${startData.y}px`;
|
||||||
|
connection.style.transform = `rotate(${angle}deg)`;
|
||||||
|
|
||||||
|
// Variation in der Animations-Geschwindigkeit
|
||||||
|
connection.style.animationDuration = `${3 + Math.random() * 4}s`;
|
||||||
|
|
||||||
|
// Speichern der verbundenen Nodes
|
||||||
|
connection._data = {
|
||||||
|
startNode: startNodeIndex,
|
||||||
|
endNode: endNodeIndex,
|
||||||
|
length
|
||||||
|
};
|
||||||
|
|
||||||
|
this.containerElement.appendChild(connection);
|
||||||
|
this.connections.push(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generateDataPackets() {
|
||||||
|
for (let i = 0; i < this.options.packetCount; i++) {
|
||||||
|
this.createNewDataPacket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createNewDataPacket() {
|
||||||
|
if (this.connections.length === 0) return;
|
||||||
|
|
||||||
|
// Zufällige Verbindung auswählen
|
||||||
|
const connectionIndex = Math.floor(Math.random() * this.connections.length);
|
||||||
|
const connection = this.connections[connectionIndex];
|
||||||
|
const connectionData = connection._data;
|
||||||
|
|
||||||
|
const startNode = this.nodes[connectionData.startNode];
|
||||||
|
const startData = startNode._data;
|
||||||
|
|
||||||
|
// Data Packet erstellen
|
||||||
|
const packet = document.createElement('div');
|
||||||
|
packet.className = 'data-packet';
|
||||||
|
|
||||||
|
// Position auf dem Startknoten
|
||||||
|
packet.style.left = `${startData.x}px`;
|
||||||
|
packet.style.top = `${startData.y}px`;
|
||||||
|
|
||||||
|
// Zufällige Geschwindigkeit
|
||||||
|
const travelTime = (4 + Math.random() * 4) / this.options.animationSpeed;
|
||||||
|
packet.style.setProperty('--travel-time', `${travelTime}s`);
|
||||||
|
|
||||||
|
// Ziel-Koordinaten berechnen
|
||||||
|
const endNode = this.nodes[connectionData.endNode];
|
||||||
|
const endData = endNode._data;
|
||||||
|
const travelX = endData.x - startData.x;
|
||||||
|
const travelY = endData.y - startData.y;
|
||||||
|
|
||||||
|
packet.style.setProperty('--travel-x', `${travelX}px`);
|
||||||
|
packet.style.setProperty('--travel-y', `${travelY}px`);
|
||||||
|
|
||||||
|
// Farb-Variation
|
||||||
|
if (Math.random() > 0.5) {
|
||||||
|
packet.style.background = 'rgba(76, 223, 255, 0.8)'; // Akzentfarbe
|
||||||
|
}
|
||||||
|
|
||||||
|
this.containerElement.appendChild(packet);
|
||||||
|
this.packets.push(packet);
|
||||||
|
|
||||||
|
// Nach Ende der Animation neues Paket erstellen
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.containerElement.contains(packet)) {
|
||||||
|
this.containerElement.removeChild(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
const index = this.packets.indexOf(packet);
|
||||||
|
if (index > -1) {
|
||||||
|
this.packets.splice(index, 1);
|
||||||
|
this.createNewDataPacket();
|
||||||
|
}
|
||||||
|
}, travelTime * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleResize() {
|
||||||
|
if (!this.initialized) return;
|
||||||
|
|
||||||
|
// Bei Größenänderung alles neu generieren
|
||||||
|
this.reset();
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
if (!this.initialized) return;
|
||||||
|
|
||||||
|
// Alle Elemente entfernen
|
||||||
|
this.nodes.forEach(node => node.remove());
|
||||||
|
this.connections.forEach(connection => connection.remove());
|
||||||
|
this.packets.forEach(packet => packet.remove());
|
||||||
|
|
||||||
|
this.nodes = [];
|
||||||
|
this.connections = [];
|
||||||
|
this.packets = [];
|
||||||
|
|
||||||
|
if (this.containerElement) {
|
||||||
|
this.containerElement.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
startAnimationCycle() {
|
||||||
|
// Regelmäßig neue Pakete erstellen für mehr Dynamik
|
||||||
|
setInterval(() => {
|
||||||
|
if (this.packets.length < this.options.packetCount * 1.5) {
|
||||||
|
this.createNewDataPacket();
|
||||||
|
}
|
||||||
|
}, 1000 / this.options.animationSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exportieren als Modul
|
||||||
|
export default CyberNetwork;
|
||||||
@@ -73,6 +73,7 @@
|
|||||||
|
|
||||||
<!-- Assistent CSS -->
|
<!-- Assistent CSS -->
|
||||||
<link href="{{ url_for('static', filename='css/assistant.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='css/assistant.css') }}" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/src/cybernetwork-bg.css') }}">
|
||||||
|
|
||||||
<!-- Basis-Stylesheet -->
|
<!-- Basis-Stylesheet -->
|
||||||
<link href="{{ url_for('static', filename='style.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='style.css') }}" rel="stylesheet">
|
||||||
@@ -154,8 +155,14 @@
|
|||||||
|
|
||||||
<!-- Seitenspezifische Styles -->
|
<!-- Seitenspezifische Styles -->
|
||||||
{% block extra_css %}{% endblock %}
|
{% block extra_css %}{% endblock %}
|
||||||
|
|
||||||
|
<!-- Cybertechnisches Netzwerk-Hintergrund -->
|
||||||
|
<script type="module" src="{{ url_for('static', filename='js/modules/cyber-network-init.js') }}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ request.endpoint }}" class="relative overflow-x-hidden">
|
<body data-page="{{ request.endpoint }}" class="relative overflow-x-hidden">
|
||||||
|
<!-- Cybertechnisches Netzwerk-Hintergrund Container (wird via JavaScript befüllt) -->
|
||||||
|
<div id="cyber-background-container" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; pointer-events: none; overflow: hidden;"></div>
|
||||||
|
|
||||||
<!-- Globaler Hintergrund -->
|
<!-- Globaler Hintergrund -->
|
||||||
<div class="full-page-bg"></div>
|
<div class="full-page-bg"></div>
|
||||||
<!-- Statischer Fallback-Hintergrund (wird nur angezeigt, wenn JavaScript deaktiviert ist) -->
|
<!-- Statischer Fallback-Hintergrund (wird nur angezeigt, wenn JavaScript deaktiviert ist) -->
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
# MindMapProjekt - Roadmap
|
|
||||||
|
|
||||||
## Projektübersicht
|
|
||||||
Das MindMapProjekt ist eine interaktive Plattform zum Visualisieren, Erforschen und Teilen von Wissen. Das Projekt wird umfassend überarbeitet, um ein modernes, benutzerfreundliches Design und erweiterte Funktionalitäten zu bieten.
|
|
||||||
|
|
||||||
## Technischer Stack
|
|
||||||
- **Backend**: Python/Flask
|
|
||||||
- **Frontend**:
|
|
||||||
- Tailwind CSS für moderne UI
|
|
||||||
- SVG-Bibliotheken für Visualisierungen (D3.js)
|
|
||||||
- JavaScript/Alpine.js für interaktive Komponenten
|
|
||||||
- **Datenbank**: SQLite mit SQLAlchemy
|
|
||||||
- **KI-Integration**: OpenAI API für intelligente Assistenz
|
|
||||||
|
|
||||||
## Installation und Verwendung
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
1. Repository klonen
|
|
||||||
2. Virtuelle Umgebung erstellen: `python -m venv venv`
|
|
||||||
3. Virtuelle Umgebung aktivieren:
|
|
||||||
- Windows: `venv\Scripts\activate`
|
|
||||||
- Unix/MacOS: `source venv/bin/activate`
|
|
||||||
4. Abhängigkeiten installieren: `pip install -r requirements.txt`
|
|
||||||
5. Datenbank initialisieren: `python TOOLS.py db:rebuild`
|
|
||||||
6. Admin-Benutzer erstellen: `python TOOLS.py user:admin`
|
|
||||||
7. Server starten: `python TOOLS.py server:run`
|
|
||||||
|
|
||||||
### Standardbenutzer
|
|
||||||
- **Admin-Benutzer**: Username: `admin` / Passwort: `admin`
|
|
||||||
- **Testbenutzer**: Username: `user` / Passwort: `user`
|
|
||||||
|
|
||||||
### Verwaltungswerkzeuge mit TOOLS.py
|
|
||||||
Das Projekt enthält ein zentrales Verwaltungsskript `TOOLS.py`, das verschiedene Hilfsfunktionen bietet:
|
|
||||||
|
|
||||||
#### Datenbankverwaltung
|
|
||||||
- `python TOOLS.py db:fix` - Reparieren der Datenbankstruktur
|
|
||||||
- `python TOOLS.py db:rebuild` - Datenbank neu aufbauen (löscht alle Daten!)
|
|
||||||
- `python TOOLS.py db:test` - Datenbankverbindung und Modelle testen
|
|
||||||
- `python TOOLS.py db:stats` - Datenbankstatistiken anzeigen
|
|
||||||
|
|
||||||
#### Benutzerverwaltung
|
|
||||||
- `python TOOLS.py user:list` - Alle Benutzer anzeigen
|
|
||||||
- `python TOOLS.py user:create -u USERNAME -e EMAIL -p PASSWORD [-a]` - Neuen Benutzer erstellen
|
|
||||||
- `python TOOLS.py user:admin` - Admin-Benutzer erstellen (admin/admin)
|
|
||||||
- `python TOOLS.py user:reset-pw -u USERNAME -p NEWPASSWORD` - Benutzerpasswort zurücksetzen
|
|
||||||
- `python TOOLS.py user:delete -u USERNAME` - Benutzer löschen
|
|
||||||
|
|
||||||
#### Serververwaltung
|
|
||||||
- `python TOOLS.py server:run [--host HOST] [--port PORT] [--no-debug]` - Entwicklungsserver starten
|
|
||||||
|
|
||||||
Für detaillierte Hilfe: `python TOOLS.py -h`
|
|
||||||
|
|
||||||
## Roadmap der Überarbeitung
|
|
||||||
|
|
||||||
### Phase 1: Grundlegende Infrastruktur ✅
|
|
||||||
- [x] Bestandsaufnahme des aktuellen Projekts
|
|
||||||
- [x] Erstellung der Roadmap
|
|
||||||
- [x] Aktualisierung der Abhängigkeiten
|
|
||||||
- [x] Integration von Tailwind CSS
|
|
||||||
- [x] Einrichtung der SVG-Bibliotheken (D3.js)
|
|
||||||
- [x] Favicon erstellen
|
|
||||||
- [x] Setup-Skript für einfache Installation
|
|
||||||
|
|
||||||
### Phase 2: Design-Überarbeitung 🔄
|
|
||||||
- [x] Implementierung des Dark Mode
|
|
||||||
- [x] Erstellung eines modernen, minimalistischen UI mit Tech-Ästhetik
|
|
||||||
- [x] Responsive Design für alle Geräte
|
|
||||||
- [ ] Gestaltung der Landing Page mit großer Typografie
|
|
||||||
|
|
||||||
### Phase 3: Mindmap-Funktionalitäten 🔄
|
|
||||||
- [x] Verbesserte Visualisierung mit SVG und D3.js
|
|
||||||
- [x] Implementierung der Mouseover-Funktion
|
|
||||||
- [x] Entwicklung der Suchfunktion für Knoten
|
|
||||||
- [ ] Tagging-System für Inhalte
|
|
||||||
- [ ] Quellenmanagement und -verlinkung
|
|
||||||
- [ ] Upload-Funktionalität an Knotenpunkten
|
|
||||||
|
|
||||||
### Phase 4: Kernseitenentwicklung
|
|
||||||
- [ ] Überarbeitung der Startseite mit neuen Features
|
|
||||||
- [ ] Entwicklung der "Wer sind wir?"-Seite
|
|
||||||
- [ ] Implementierung von Impressum und Datenschutzerklärung
|
|
||||||
- [ ] Erstellung der Kontaktseite mit FAQs
|
|
||||||
- [ ] Überarbeitung des Benutzerprofilbereichs
|
|
||||||
|
|
||||||
### Phase 5: Community-Features
|
|
||||||
- [ ] Entwicklung des Autorenbereichs
|
|
||||||
- [ ] Implementierung von Community-Bereichen für Themenbereiche
|
|
||||||
- [ ] Verbesserter Kommentarbereich
|
|
||||||
- [ ] Benutzerrechtemanagement
|
|
||||||
|
|
||||||
### Phase 6: KI-Integration
|
|
||||||
- [ ] Implementierung des Frage-Antwort-Systems
|
|
||||||
- [ ] KI-generierte Themeneinleitungen
|
|
||||||
- [ ] Intelligente Suchunterstützung
|
|
||||||
- [ ] Geführte Pfade durch Themenbereiche
|
|
||||||
- [ ] Vorgeschlagene Chat-Möglichkeiten
|
|
||||||
|
|
||||||
### Phase 7: Benutzerprofilfunktionen
|
|
||||||
- [ ] Speichern von Thematiken
|
|
||||||
- [ ] Persönliche Mindmap/Pinboard
|
|
||||||
- [ ] Beitragsmanagement
|
|
||||||
- [ ] Benutzerstatistiken und -aktivitäten
|
|
||||||
|
|
||||||
### Phase 8: Testing und Optimierung
|
|
||||||
- [ ] Umfassende Tests aller Funktionen
|
|
||||||
- [ ] Performance-Optimierung
|
|
||||||
- [ ] SEO-Implementierung
|
|
||||||
- [ ] Barrierefreiheit prüfen und verbessern
|
|
||||||
|
|
||||||
### Phase 9: Dokumentation und Einführung
|
|
||||||
- [ ] Erstellung von Benutzeranleitungen
|
|
||||||
- [ ] Entwicklerdokumentation
|
|
||||||
- [ ] Administratorenhandbuch
|
|
||||||
- [ ] Guided Tour für neue Benutzer
|
|
||||||
|
|
||||||
## Aktueller Status
|
|
||||||
- **Phase 1**: ✅ Abgeschlossen
|
|
||||||
- **Phase 2**: 🔄 In Bearbeitung (75% abgeschlossen)
|
|
||||||
- **Phase 3**: 🔄 In Bearbeitung (50% abgeschlossen)
|
|
||||||
|
|
||||||
## Aktuelle Fortschritte
|
|
||||||
- Grundlegende UI modernisiert mit Tailwind CSS und Dark Mode
|
|
||||||
- Neues Favicon für bessere visuelle Identität erstellt
|
|
||||||
- Setup-Prozess vereinfacht mit einem Shell-Skript
|
|
||||||
- Mindmap-Visualisierung komplett überarbeitet mit D3.js für eine interaktivere Erfahrung
|
|
||||||
- Responsive Design für optimale Darstellung auf allen Geräten
|
|
||||||
|
|
||||||
## Nächste Schritte
|
|
||||||
- Fertigstellung der Landing Page
|
|
||||||
- Erstellung der "Wer sind wir?"-Seite
|
|
||||||
- Implementierung des Tagging-Systems für Gedanken
|
|
||||||
- Verbesserung der Gedankenansicht im Mindmap-Bereich
|
|
||||||
|
|
||||||
*Zuletzt aktualisiert: 01.06.2024*
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,14 +0,0 @@
|
|||||||
flask==2.2.5
|
|
||||||
flask-login==0.6.2
|
|
||||||
flask-wtf
|
|
||||||
email-validator
|
|
||||||
python-dotenv
|
|
||||||
werkzeug==2.2.3
|
|
||||||
flask-sqlalchemy==3.0.5
|
|
||||||
openai==1.3.0
|
|
||||||
requests==2.31.0
|
|
||||||
flask-cors==4.0.0
|
|
||||||
gunicorn==21.2.0
|
|
||||||
#pillow==10.0.1
|
|
||||||
pytest==7.4.0
|
|
||||||
pytest-flask==1.2.0
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
from init_db import init_database
|
|
||||||
from app import app
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# Lade .env-Datei explizit
|
|
||||||
env_path = Path(__file__).parent / ".env"
|
|
||||||
if env_path.exists():
|
|
||||||
print(f"Lade Umgebungsvariablen aus {env_path}")
|
|
||||||
load_dotenv(dotenv_path=env_path, override=True, force=True)
|
|
||||||
else:
|
|
||||||
print("Warnung: .env-Datei nicht gefunden!")
|
|
||||||
|
|
||||||
# Check if CSS file exists, build it if it doesn't
|
|
||||||
css_file = Path(__file__).parent / "static" / "css" / "main.css"
|
|
||||||
if not css_file.exists():
|
|
||||||
print("CSS file not found. Building with Tailwind...")
|
|
||||||
try:
|
|
||||||
from build_css import build_css
|
|
||||||
build_css()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Warning: Failed to build CSS: {e}")
|
|
||||||
print("You may need to run 'python build_css.py' manually.")
|
|
||||||
|
|
||||||
# Initialize the database first
|
|
||||||
init_database()
|
|
||||||
|
|
||||||
# Run the Flask application
|
|
||||||
app.run(debug=True, host='0.0.0.0', port=5000)
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Farben für Ausgaben
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
YELLOW='\033[0;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
echo -e "${GREEN}==== MindMap Projekt Setup ====${NC}"
|
|
||||||
|
|
||||||
# Verzeichnis erstellen, wenn nicht vorhanden
|
|
||||||
echo -e "${BLUE}Überprüfe Verzeichnisstruktur...${NC}"
|
|
||||||
mkdir -p static/css/src
|
|
||||||
mkdir -p static/img
|
|
||||||
mkdir -p static/js
|
|
||||||
mkdir -p bin
|
|
||||||
|
|
||||||
# Überprüfe, ob .env-Datei existiert und erstelle sie, wenn nicht
|
|
||||||
echo -e "${BLUE}Überprüfe .env-Datei...${NC}"
|
|
||||||
if [ ! -f ".env" ]; then
|
|
||||||
echo -e "${YELLOW}Keine .env-Datei gefunden. Erstelle neue .env-Datei aus example.env...${NC}"
|
|
||||||
cp example.env .env
|
|
||||||
echo -e "${YELLOW}Bitte bearbeiten Sie die .env-Datei und setzen Sie die erforderlichen Werte.${NC}"
|
|
||||||
echo -e "${YELLOW}Insbesondere müssen Sie einen gültigen API-Schlüssel für OpenAI setzen.${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${GREEN}.env-Datei existiert bereits.${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Python-Abhängigkeiten installieren
|
|
||||||
echo -e "${BLUE}Installiere Python-Abhängigkeiten...${NC}"
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Zusätzliche Abhängigkeiten für Favicon-Erstellung
|
|
||||||
echo -e "${BLUE}Installiere Abhängigkeiten für Favicon-Erstellung...${NC}"
|
|
||||||
pip install pillow cairosvg
|
|
||||||
|
|
||||||
# Tailwind CSS mit Python-Skript kompilieren
|
|
||||||
echo -e "${BLUE}Kompiliere Tailwind CSS...${NC}"
|
|
||||||
python build_css.py
|
|
||||||
|
|
||||||
# Favicon generieren
|
|
||||||
echo -e "${BLUE}Generiere Favicon...${NC}"
|
|
||||||
python static/img/favicon-gen.py
|
|
||||||
|
|
||||||
# Erstelle die Datenbank
|
|
||||||
echo -e "${BLUE}Initialisiere die Datenbank...${NC}"
|
|
||||||
python init_db.py
|
|
||||||
|
|
||||||
echo -e "${GREEN}==== Setup abgeschlossen ====${NC}"
|
|
||||||
echo -e "${GREEN}Starte die Anwendung mit: python run.py${NC}"
|
|
||||||
echo -e "${GREEN}Für Entwicklung mit CSS-Autoreload: python dev.py${NC}"
|
|
||||||
Reference in New Issue
Block a user