add element web
This commit is contained in:
parent
98417edd8b
commit
000ec5d25f
9 changed files with 209 additions and 236 deletions
150
README.md
150
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.
|
||||
|
||||
[](https://www.docker.com/)
|
||||
[](https://fastapi.tiangolo.com/)
|
||||
|
|
@ -33,100 +33,84 @@
|
|||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Studio EinsZwoVier Web App (Port 80)"
|
||||
LP[🏠 Landing Page<br/>studio-einszwovier.local]
|
||||
About[ℹ️ About Page<br/>/about<br/>Courses + Team Info]
|
||||
Cost[💰 Cost Calculator<br/>/cost<br/>PDF Analysis]
|
||||
|
||||
subgraph "studio einszwovier Web Platform"
|
||||
LP[🏠 Landing Page<br/>Port 80]
|
||||
About[ℹ️ About Page<br/>/about]
|
||||
CostCalc[💰 Cost Calculator<br/>/cost]
|
||||
|
||||
LP --> About
|
||||
LP --> Cost
|
||||
LP --> CostCalc
|
||||
end
|
||||
|
||||
subgraph "Course Management"
|
||||
CSV[📝 courses.csv<br/>Title, Description, Dates, Image]
|
||||
Images[🖼️ Course Images<br/>static/images/courses/]
|
||||
Modal[🔍 Image Modal<br/>Click to Enlarge]
|
||||
|
||||
About --> CSV
|
||||
CSV --> Images
|
||||
Images --> Modal
|
||||
subgraph "Services Accessible from Landing Page"
|
||||
BookStack[<5B> BookStack<br/>Port 6875<br/>Wissenssammlung]
|
||||
OpenWebUI[🤖 Open WebUI<br/>Port 8080<br/>LLM Chatbot]
|
||||
JupyterHub[<5B> JupyterHub<br/>Port 8001<br/>Python Notebooks]
|
||||
Forgejo[🦊 Forgejo<br/>Port 3003<br/>Git Server]
|
||||
ElementWeb[<5B> Element Web<br/>Port 8082<br/>Matrix Chat]
|
||||
Portainer[<5B> Portainer<br/>Port 9000<br/>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<br/>- Dimensions<br/>- Ink Coverage<br/>- Color Detection]
|
||||
Quote[📋 Quote Generation<br/>Per-page Breakdown]
|
||||
|
||||
Cost --> Upload
|
||||
Upload --> Analysis
|
||||
Analysis --> Quote
|
||||
end
|
||||
|
||||
subgraph "Matrix Integration"
|
||||
MatrixRoom[💬 Matrix Room<br/>Print Orders]
|
||||
PDF_Upload[📎 PDF Attachment]
|
||||
Summary[📊 Order Summary<br/>German Language]
|
||||
|
||||
Quote --> MatrixRoom
|
||||
Quote --> PDF_Upload
|
||||
Quote --> Summary
|
||||
end
|
||||
|
||||
subgraph "Integrated Services"
|
||||
BookStack[📚 BookStack Wiki<br/>:6875]
|
||||
Ollama[🤖 Ollama LLM<br/>:11434]
|
||||
OpenWebUI[💭 Open WebUI<br/>:8080]
|
||||
Portainer[🐳 Portainer<br/>:9000]
|
||||
Synapse[📨 Matrix Synapse<br/>:8008]
|
||||
JupyterHub[📓 JupyterHub<br/>:8001<br/>Drone Programming]
|
||||
Forgejo[🦊 Forgejo Git<br/>:3003<br/>Code Collaboration]
|
||||
|
||||
LP -.-> BookStack
|
||||
LP -.-> OpenWebUI
|
||||
LP -.-> Portainer
|
||||
LP -.-> JupyterHub
|
||||
LP -.-> Forgejo
|
||||
subgraph "Backend Services"
|
||||
Synapse[<5B> Synapse<br/>Port 8008<br/>Matrix Server]
|
||||
Ollama[🔮 Ollama<br/>Port 11434<br/>LLM Engine]
|
||||
MariaDB[(<28> MariaDB<br/>BookStack DB)]
|
||||
|
||||
ElementWeb --> Synapse
|
||||
OpenWebUI --> Ollama
|
||||
MatrixRoom --> Synapse
|
||||
BookStack --> MariaDB
|
||||
CostCalc --> Synapse
|
||||
end
|
||||
|
||||
subgraph "Educational Stack"
|
||||
Notebooks[📒 Jupyter Notebooks<br/>Python Drone Code]
|
||||
GitRepos[📦 Git Repositories<br/>Project Source Code]
|
||||
DronePackages[🚁 djitellopy<br/>Tello SDK]
|
||||
|
||||
subgraph "Educational Resources"
|
||||
Notebooks[📒 Drone Programming<br/>djitellopy Package]
|
||||
GitRepos[📦 Code Repositories<br/>Project Source]
|
||||
Knowledge[<5B> Documentation<br/>Guides & Tutorials]
|
||||
|
||||
JupyterHub --> Notebooks
|
||||
Forgejo --> GitRepos
|
||||
Notebooks -.-> DronePackages
|
||||
BookStack --> Knowledge
|
||||
end
|
||||
|
||||
subgraph "Data Persistence"
|
||||
Uploads[📁 data/uploads/<br/>PDF Files]
|
||||
Courses[📋 data/courses.csv<br/>Course List]
|
||||
MatrixDB[(🗄️ Matrix DB<br/>homeserver.db)]
|
||||
BookDB[(🗄️ BookStack DB<br/>MariaDB)]
|
||||
JupyterVolumes[(💾 Jupyter Volumes<br/>User Workspaces)]
|
||||
ForgejoData[(📚 Forgejo Data<br/>Git Repos)]
|
||||
|
||||
Upload --> Uploads
|
||||
CSV --> Courses
|
||||
Synapse --> MatrixDB
|
||||
BookStack --> BookDB
|
||||
JupyterHub --> JupyterVolumes
|
||||
subgraph "Persistent Storage"
|
||||
PDFUploads[📁 PDF Files<br/>data/uploads/]
|
||||
CoursesCSV[📋 Courses CSV<br/>data/courses.csv]
|
||||
MatrixData[(🗄️ Matrix Data<br/>matrix/data/)]
|
||||
JupyterVols[(💾 Jupyter Volumes<br/>User Workspaces)]
|
||||
ForgejoData[(📚 Forgejo Data<br/>forgejo/data/)]
|
||||
|
||||
CostCalc --> PDFUploads
|
||||
About --> CoursesCSV
|
||||
Synapse --> MatrixData
|
||||
JupyterHub --> JupyterVols
|
||||
Forgejo --> ForgejoData
|
||||
end
|
||||
|
||||
subgraph "Infrastructure"
|
||||
Watchtower[🔄 Watchtower<br/>Auto-Updates<br/>Every 24h]
|
||||
Network[🌐 einszwovier_network<br/>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
|
||||
|
|
|
|||
|
|
@ -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!"
|
||||
|
|
@ -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
|
||||
|
|
|
|||
74
element-web/README.md
Normal file
74
element-web/README.md
Normal file
|
|
@ -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**
|
||||
27
element-web/config.json
Normal file
27
element-web/config.json
Normal file
|
|
@ -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
|
||||
}
|
||||
5
main.py
5
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."},
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}Studio Einszwovier{% endblock %}</title>
|
||||
<title>{% block title %}studio einszwovier{% endblock %}</title>
|
||||
<link rel="stylesheet" href="/static/css/style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<a href="/" class="logo-link">
|
||||
<img src="/static/images/logo.png" alt="Studio Einszwovier Logo" class="logo">
|
||||
<img src="/static/images/logo.png" alt="studio einszwovier Logo" class="logo">
|
||||
</a>
|
||||
<nav>
|
||||
<a href="/">Startseite</a> |
|
||||
|
|
|
|||
|
|
@ -72,6 +72,12 @@
|
|||
Entwicklung und Projektmanagement.</div>
|
||||
</a>
|
||||
|
||||
<a class="link-card" href="http://{{ server_hostname }}:{{ element_port }}" target="_blank">
|
||||
<div class="title">Matrix Chat</div>
|
||||
<div class="tagline">Browser-basierter Chat für die studio einszwovier Community. Nutzt den bestehenden
|
||||
Matrix-Server – keine App-Installation nötig.</div>
|
||||
</a>
|
||||
|
||||
<a class="link-card" href="mailto:einszwovier@gvb-gymnasium.de" target="_blank">
|
||||
<div class="title">Kontakt</div>
|
||||
<div class="tagline">Schreibe uns direkt an: einszwovier@gvb-gymnasium.de</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<!-- templates/result.html -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Druckkosten Ergebnis – Studio EinsZwoVier{% endblock %}
|
||||
{% block title %}Druckkosten Ergebnis – studio einszwovier{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
|
|
@ -70,7 +70,8 @@
|
|||
<input type="text" id="name" name="name" required placeholder="Dein Name">
|
||||
|
||||
<label for="comment"><strong>Zusätzliche Hinweise:</strong></label>
|
||||
<textarea id="comment" name="comment" rows="4" placeholder="z. B. doppelseitig oder spezielles Papier"></textarea>
|
||||
<textarea id="comment" name="comment" rows="4"
|
||||
placeholder="z. B. doppelseitig oder spezielles Papier"></textarea>
|
||||
|
||||
<button type="submit">Auftrag senden</button>
|
||||
</form>
|
||||
|
|
@ -79,4 +80,4 @@
|
|||
<a href="/">Neues PDF hochladen</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue