diff --git a/README.md b/README.md index 0c88c01..906a67a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Studio EinsZwoVier Web Application +# studio einszwovier Web Application -**FastAPI-based PDF print cost calculator** with automated ink coverage analysis, Matrix integration, and multi-service hub for Studio EinsZwoVier Maker Space. +**FastAPI-based PDF print cost calculator** with automated ink coverage analysis, Matrix integration, and multi-service hub for studio einszwovier Maker Space. [![Docker](https://img.shields.io/badge/Docker-Ready-2496ED?logo=docker)](https://www.docker.com/) [![FastAPI](https://img.shields.io/badge/FastAPI-0.104+-009688?logo=fastapi)](https://fastapi.tiangolo.com/) @@ -33,100 +33,84 @@ ```mermaid graph TB - subgraph "Studio EinsZwoVier Web App (Port 80)" - LP[๐Ÿ  Landing Page
studio-einszwovier.local] - About[โ„น๏ธ About Page
/about
Courses + Team Info] - Cost[๐Ÿ’ฐ Cost Calculator
/cost
PDF Analysis] - + subgraph "studio einszwovier Web Platform" + LP[๐Ÿ  Landing Page
Port 80] + About[โ„น๏ธ About Page
/about] + CostCalc[๐Ÿ’ฐ Cost Calculator
/cost] + LP --> About - LP --> Cost + LP --> CostCalc end - subgraph "Course Management" - CSV[๐Ÿ“ courses.csv
Title, Description, Dates, Image] - Images[๐Ÿ–ผ๏ธ Course Images
static/images/courses/] - Modal[๐Ÿ” Image Modal
Click to Enlarge] - - About --> CSV - CSV --> Images - Images --> Modal + subgraph "Services Accessible from Landing Page" + BookStack[๏ฟฝ BookStack
Port 6875
Wissenssammlung] + OpenWebUI[๐Ÿค– Open WebUI
Port 8080
LLM Chatbot] + JupyterHub[๏ฟฝ JupyterHub
Port 8001
Python Notebooks] + Forgejo[๐ŸฆŠ Forgejo
Port 3003
Git Server] + ElementWeb[๏ฟฝ Element Web
Port 8082
Matrix Chat] + Portainer[๏ฟฝ Portainer
Port 9000
Admin Panel] + + LP -.->|Link| BookStack + LP -.->|Link| OpenWebUI + LP -.->|Link| JupyterHub + LP -.->|Link| Forgejo + LP -.->|Link| ElementWeb + LP -.->|Link| Portainer end - subgraph "PDF Processing Pipeline" - Upload[๐Ÿ“ค Upload PDF] - Analysis[๐Ÿ”ฌ Analyze
- Dimensions
- Ink Coverage
- Color Detection] - Quote[๐Ÿ“‹ Quote Generation
Per-page Breakdown] - - Cost --> Upload - Upload --> Analysis - Analysis --> Quote - end - - subgraph "Matrix Integration" - MatrixRoom[๐Ÿ’ฌ Matrix Room
Print Orders] - PDF_Upload[๐Ÿ“Ž PDF Attachment] - Summary[๐Ÿ“Š Order Summary
German Language] - - Quote --> MatrixRoom - Quote --> PDF_Upload - Quote --> Summary - end - - subgraph "Integrated Services" - BookStack[๐Ÿ“š BookStack Wiki
:6875] - Ollama[๐Ÿค– Ollama LLM
:11434] - OpenWebUI[๐Ÿ’ญ Open WebUI
:8080] - Portainer[๐Ÿณ Portainer
:9000] - Synapse[๐Ÿ“จ Matrix Synapse
:8008] - JupyterHub[๐Ÿ““ JupyterHub
:8001
Drone Programming] - Forgejo[๐ŸฆŠ Forgejo Git
:3003
Code Collaboration] - - LP -.-> BookStack - LP -.-> OpenWebUI - LP -.-> Portainer - LP -.-> JupyterHub - LP -.-> Forgejo + subgraph "Backend Services" + Synapse[๏ฟฝ Synapse
Port 8008
Matrix Server] + Ollama[๐Ÿ”ฎ Ollama
Port 11434
LLM Engine] + MariaDB[(๏ฟฝ MariaDB
BookStack DB)] + + ElementWeb --> Synapse OpenWebUI --> Ollama - MatrixRoom --> Synapse + BookStack --> MariaDB + CostCalc --> Synapse end - subgraph "Educational Stack" - Notebooks[๐Ÿ“’ Jupyter Notebooks
Python Drone Code] - GitRepos[๐Ÿ“ฆ Git Repositories
Project Source Code] - DronePackages[๐Ÿš djitellopy
Tello SDK] - + subgraph "Educational Resources" + Notebooks[๐Ÿ“’ Drone Programming
djitellopy Package] + GitRepos[๐Ÿ“ฆ Code Repositories
Project Source] + Knowledge[๏ฟฝ Documentation
Guides & Tutorials] + JupyterHub --> Notebooks Forgejo --> GitRepos - Notebooks -.-> DronePackages + BookStack --> Knowledge end - subgraph "Data Persistence" - Uploads[๐Ÿ“ data/uploads/
PDF Files] - Courses[๐Ÿ“‹ data/courses.csv
Course List] - MatrixDB[(๐Ÿ—„๏ธ Matrix DB
homeserver.db)] - BookDB[(๐Ÿ—„๏ธ BookStack DB
MariaDB)] - JupyterVolumes[(๐Ÿ’พ Jupyter Volumes
User Workspaces)] - ForgejoData[(๐Ÿ“š Forgejo Data
Git Repos)] - - Upload --> Uploads - CSV --> Courses - Synapse --> MatrixDB - BookStack --> BookDB - JupyterHub --> JupyterVolumes + subgraph "Persistent Storage" + PDFUploads[๐Ÿ“ PDF Files
data/uploads/] + CoursesCSV[๐Ÿ“‹ Courses CSV
data/courses.csv] + MatrixData[(๐Ÿ—„๏ธ Matrix Data
matrix/data/)] + JupyterVols[(๐Ÿ’พ Jupyter Volumes
User Workspaces)] + ForgejoData[(๐Ÿ“š Forgejo Data
forgejo/data/)] + + CostCalc --> PDFUploads + About --> CoursesCSV + Synapse --> MatrixData + JupyterHub --> JupyterVols Forgejo --> ForgejoData end + subgraph "Infrastructure" + Watchtower[๐Ÿ”„ Watchtower
Auto-Updates
Every 24h] + Network[๐ŸŒ einszwovier_network
Docker Network] + end + classDef webapp fill:#e3f2fd,stroke:#1976d2,stroke-width:2px classDef service fill:#fff3e0,stroke:#f57c00,stroke-width:2px - classDef data fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px - classDef matrix fill:#e8f5e9,stroke:#388e3c,stroke-width:2px + classDef backend fill:#e8f5e9,stroke:#388e3c,stroke-width:2px + classDef storage fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px classDef edu fill:#fce4ec,stroke:#c2185b,stroke-width:2px + classDef infra fill:#fafafa,stroke:#616161,stroke-width:2px - class LP,About,Cost,Upload,Analysis,Quote webapp - class BookStack,Ollama,OpenWebUI,Portainer,Synapse,JupyterHub,Forgejo service - class Uploads,Courses,MatrixDB,BookDB,JupyterVolumes,ForgejoData data - class MatrixRoom,PDF_Upload,Summary,CSV,Images,Modal matrix - class Notebooks,GitRepos,DronePackages edu + class LP,About,CostCalc webapp + class BookStack,OpenWebUI,JupyterHub,Forgejo,ElementWeb,Portainer service + class Synapse,Ollama,MariaDB backend + class PDFUploads,CoursesCSV,MatrixData,JupyterVols,ForgejoData storage + class Notebooks,GitRepos,Knowledge edu + class Watchtower,Network infra ``` --- @@ -380,7 +364,7 @@ docker compose up --build ### Project Structure -``` +```zsh . โ”œโ”€โ”€ main.py # FastAPI application โ”œโ”€โ”€ cost_calculator.py # PDF analysis logic @@ -417,7 +401,7 @@ docker compose up --build ## ๐Ÿค Contributing -Contributions are welcome! This is part of **Studio EinsZwoVier**, a collaborative Maker Space. +Contributions are welcome! This is part of **studio einszwovier**, a collaborative Maker Space. 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) @@ -429,13 +413,13 @@ Contributions are welcome! This is part of **Studio EinsZwoVier**, a collaborati ## ๐Ÿ“„ License -This project is part of Studio EinsZwoVier educational initiative. +This project is part of studio einszwovier educational initiative. --- ## ๐Ÿ“ž Contact -**Studio EinsZwoVier** +**studio einszwovier** Gabriele-von-Bรผlow-Gymnasium Tile-Brรผgge-Weg 63, 13509 Berlin (Tegel) @@ -452,8 +436,8 @@ Tile-Brรผgge-Weg 63, 13509 Berlin (Tegel) - Ollama team for local LLM support - BookStack for the documentation platform - FastAPI community -- All contributors and students of Studio EinsZwoVier +- All contributors and students of studio einszwovier --- -**Made with โค๏ธ at Studio EinsZwoVier Maker Space** +Made with โค๏ธ at studio einszwovier Maker Space diff --git a/data/KURSE_README.md b/data/KURSE_README.md deleted file mode 100644 index 9cde519..0000000 --- a/data/KURSE_README.md +++ /dev/null @@ -1,147 +0,0 @@ -# Kurse verwalten - -## Kurse bearbeiten - -Die aktuellen Kurse werden aus der Datei `courses.csv` geladen und automatisch auf der "รœber uns" Seite angezeigt. - -### CSV-Format - -Die Datei hat fรผnf Spalten (alle auรŸer `title` sind optional): -- `title` - Der Titel des Kurses (erforderlich) -- `description` - Eine kurze Beschreibung (optional) -- `dates` - Termine und Zeiten (optional) -- `offen_fuer` - Zielgruppe/Altersgruppe (optional) -- `image` - Pfad zum Kursbild (optional) - -**Beispiel:** -```csv -title,description,dates,offen_fuer,image -Lรถten und Leuchten,Herstellung von Nachttischleuchten mit 3D-Design und Lรถttechnik,"Di 15.10. 14:00-16:00",Klasse 7-9,/static/images/courses/loeten.jpg -Die Vogelvilla,Bau von Vogelhรคusern mit Lasercutter und Holzbearbeitung,"Mi 23.10. 13:00-15:00",alle Schรผler:innen, -Robotik Intro,,,ab Klasse 5,/static/images/courses/robotik.jpg -``` - -### Kursbilder hinzufรผgen - -1. Speichere das Bild in `/static/images/courses/` -2. Verwende den Pfad `/static/images/courses/dein-bild.jpg` in der CSV -3. Empfohlene BildgrรถรŸe: mindestens 640x400 Pixel -4. Unterstรผtzte Formate: JPG, PNG, WebP - -**Tipp:** Wenn kein Bild angegeben ist, wird der Kurs ohne Bild angezeigt (nur Text).### Felder im Detail - -#### `title` (erforderlich) -Der Kursname - wird immer angezeigt. - -#### `description` (optional) -Kurzbeschreibung des Kurses. Wird nur angezeigt, wenn vorhanden. - -#### `dates` (optional) -Termine und Uhrzeiten. Kann mehrere Termine enthalten: -- Einzelner Termin: `Mi 23.10. 13:00-15:00` -- Mehrere Termine: `Di 15.10. 14:00-16:00, Do 17.10. 14:00-16:00` -- Bei Terminen mit Kommas: In Anfรผhrungszeichen setzen - -#### `offen_fuer` (optional) -Freitextfeld fรผr die Zielgruppe: -- `Klasse 7-9` -- `alle Schรผler:innen` -- `ab 14 Jahren` -- `Oberstufe` - -### Kurs hinzufรผgen - -Einfach eine neue Zeile am Ende der Datei hinzufรผgen: -```csv -title,description,dates,offen_fuer -Lรถten und Leuchten,Herstellung von Nachttischleuchten mit 3D-Design und Lรถttechnik,"Di 15.10. 14:00-16:00, Do 17.10. 14:00-16:00",Klasse 7-9 -Neuer Kurs,Beschreibung des neuen Kurses,"Mo 20.10. 15:00-17:00",Klasse 8-10 -``` - -### Fehlende Informationen - -Alle Felder auรŸer `title` sind optional. Beispiele: - -**Nur Titel und Beschreibung:** -```csv -title,description,dates,offen_fuer -Workshop XYZ,Toller Workshop รผber Making,, -``` - -**Nur Titel und Termine:** -```csv -title,description,dates,offen_fuer -Workshop ABC,,"Fr 25.10. 14:00", -``` - -**Nur Titel und Zielgruppe:** -```csv -title,description,dates,offen_fuer -Workshop 123,,,Klasse 9-10 -``` - -### Kurs entfernen - -Einfach die entsprechende Zeile lรถschen. - -### Wichtig - -- **Keine Anfรผhrungszeichen** verwenden, auรŸer der Text enthรคlt ein Komma -- **Keine Zeilenumbrรผche** innerhalb der Beschreibung -- Die erste Zeile (`title,description,dates,offen_fuer,image`) muss erhalten bleiben -- Nach dem Speichern wird die ร„nderung sofort auf der Website sichtbar - -### Darstellung auf der Website - -Die Kurse werden in einem **Grid-Layout** mit **Karten-Design** angezeigt: - -- **GroรŸe, fette Titel** (1.5em) mit pinker Unterstreichung -- **Hover-Effekt**: Karten heben sich beim รœberfahren an -- **Responsive**: Auf Mobilgerรคten eine Spalte, auf Desktop mehrere Spalten -- **Kursbilder** (optional): 200px hoch, oben auf der Karte -- **Metadata** am unteren Rand: Datum und Zielgruppe mit Icons - -**Beispiel mit Bild:** -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ [Kursbild 640x400] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ Lรถten und Leuchten โ”‚ โ† 1.5em, fett, pink unterstrichen -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ -โ”‚ โ”‚ -โ”‚ Herstellung von Nachtisch- โ”‚ โ† Beschreibung -โ”‚ leuchten mit 3D-Design โ”‚ -โ”‚ โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ ๐Ÿ“… Dez. '24 โ”‚ โ† Metadata mit Icons -โ”‚ ๐Ÿ‘ฅ Klasse 5-6 โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` - -**Beispiel ohne Bild:** -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ Textiles Plotten โ”‚ โ† Direkt der Titel -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ -โ”‚ โ”‚ -โ”‚ Erschaffe deine eigenen โ”‚ -โ”‚ Klamottendesigns โ”‚ -โ”‚ โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ ๐Ÿ“… Mai '25 โ”‚ -โ”‚ ๐Ÿ‘ฅ Jhg. 9 โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` - -### Live-Update - -Die Kurse werden bei jedem Seitenaufruf neu geladen. Es ist **kein Neustart** des Servers erforderlich! - -### Keine Kurse anzeigen - -Wenn keine Kurse stattfinden, einfach alle Zeilen auรŸer der Kopfzeile lรถschen: -```csv -title,description -``` - -Die Seite zeigt dann: "Aktuell sind keine Kurse geplant. Schaut bald wieder vorbei!" diff --git a/docker-compose.yml b/docker-compose.yml index d5fcf01..f37d89f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -264,6 +264,31 @@ services: - "description=Forgejo Git Server" - "maintainer=Studio EinsZwoVier" + element-web: + image: vectorim/element-web:latest + container_name: element-web + restart: unless-stopped + ports: + - "${ELEMENT_PORT:-8082}:80" + volumes: + - ./element-web/config.json:/app/config.json:ro + mem_limit: 512m + cpus: 0.5 + mem_reservation: 128m + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + depends_on: + synapse: + condition: service_started + labels: + - "com.centurylinklabs.watchtower.enable=true" + - "description=Element Web Matrix Client" + - "maintainer=studio einszwovier" + volumes: portainer_data: driver: local diff --git a/element-web/README.md b/element-web/README.md new file mode 100644 index 0000000..06c8a5c --- /dev/null +++ b/element-web/README.md @@ -0,0 +1,74 @@ +# Element Web - Matrix Client + +Element Web is a browser-based Matrix client that connects to the studio einszwovier Matrix (Synapse) server. + +## Configuration + +The `config.json` file configures Element Web to connect to the local Synapse homeserver at `http://einszwovier.local:8008`. + +### Key Settings + +- **Homeserver**: Points to local Synapse instance +- **Server name**: `einszwovier.local` +- **Brand**: "studio einszwovier Chat" +- **Default language**: German (DE) +- **Default theme**: Light mode +- **Guest access**: Enabled (users can preview without account) + +## Access + +- **URL**: `http://einszwovier.local:8082` +- **No app required**: Works in any modern web browser +- **Mobile friendly**: Responsive design works on phones and tablets + +## Usage + +1. Navigate to `http://einszwovier.local:8082` +2. Click "Sign In" or "Create Account" +3. Use existing Matrix credentials or create a new account +4. Join rooms (e.g., the print order room) +5. Chat, share files, and collaborate! + +## Features + +- โœ… End-to-end encryption +- โœ… File sharing and media uploads +- โœ… Read receipts and typing indicators +- โœ… Markdown formatting +- โœ… Voice and video calls (browser-to-browser) +- โœ… Room directory browsing +- โœ… Cross-device message sync + +## Updates + +Element Web is managed by Watchtower and updates automatically with the rest of the stack. + +## Troubleshooting + +**Can't connect to homeserver:** + +- Ensure Synapse is running: `docker-compose ps synapse` +- Check Synapse logs: `docker-compose logs synapse` +- Verify hostname resolution: `ping einszwovier.local` + +**Login fails:** + +- Verify credentials with Matrix admin +- Check Synapse registration settings in `matrix/data/homeserver.yaml` + +**Performance issues:** + +- Element Web is resource-intensive for large rooms +- Consider using Hydrogen (lighter client) for low-end devices +- Clear browser cache and reload + +## Security Notes + +- Element Web runs on HTTP in the local network +- For production/internet exposure, configure HTTPS via reverse proxy +- User sessions are stored in browser local storage +- Encryption keys are managed client-side + +--- + +**Maintained by studio einszwovier** diff --git a/element-web/config.json b/element-web/config.json new file mode 100644 index 0000000..3497c3f --- /dev/null +++ b/element-web/config.json @@ -0,0 +1,27 @@ +{ + "default_server_config": { + "m.homeserver": { + "base_url": "http://einszwovier.local:8008", + "server_name": "einszwovier.local" + } + }, + "brand": "studio einszwovier Chat", + "disable_guests": false, + "disable_login_language_selector": false, + "default_country_code": "DE", + "show_labs_settings": false, + "default_theme": "light", + "settingDefaults": { + "language": "de" + }, + "room_directory": { + "servers": [ + "einszwovier.local" + ] + }, + "enable_presence_by_hs_url": { + "http://einszwovier.local:8008": true + }, + "terms_and_conditions_links": [], + "privacy_policy_url": null +} \ No newline at end of file diff --git a/main.py b/main.py index 89a5b61..3f477a3 100644 --- a/main.py +++ b/main.py @@ -19,6 +19,7 @@ BOOKSTACK_PORT = os.environ.get("BOOKSTACK_PORT", "6875") OPENWEBUI_PORT = os.environ.get("OPENWEBUI_PORT", "8080") PORTAINER_PORT = os.environ.get("PORTAINER_PORT", "9000") FORGEJO_PORT = os.environ.get("FORGEJO_PORT", "3003") +ELEMENT_PORT = os.environ.get("ELEMENT_PORT", "8082") # Courses CSV path COURSES_CSV = Path("data/courses.csv") @@ -86,6 +87,7 @@ async def welcome(request: Request): "openwebui_port": OPENWEBUI_PORT, "portainer_port": PORTAINER_PORT, "forgejo_port": FORGEJO_PORT, + "element_port": ELEMENT_PORT, }, ) @@ -120,7 +122,8 @@ async def cost_dashboard(request: Request): @app.post("/upload") async def upload_file(request: Request, file: UploadFile = File(...)): - if not allowed_file(file.filename): + # Ensure filename is present (UploadFile.filename can be None) before validation + if not file.filename or not allowed_file(file.filename): return templates.TemplateResponse( "cost-calculator.html", {"request": request, "error": "Unsupported file type. Only PDF allowed."}, diff --git a/templates/base.html b/templates/base.html index 3d31d82..7bf6cb0 100644 --- a/templates/base.html +++ b/templates/base.html @@ -3,14 +3,14 @@ - {% block title %}Studio Einszwovier{% endblock %} + {% block title %}studio einszwovier{% endblock %}
- +