diff --git a/AGENTS.md b/AGENTS.md index 2b1b324..4ef8496 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,6 +8,8 @@ - `templates/settings.html` — Einstellungsseite (Druckerabschreibung, Arbeitskosten, Marge, MwSt., Firmendaten, Logo) - `static/style.css` — Light-/Dark-Mode-Theming - `static/script.js` — Live-Berechnung + Auto-Save beim Tippen +- `static/img/logo/` — JET-Design-Wortmarke: `jet-design.svg` (dunkle Schrift), + `jet-design-weiss.svg` (Dark Mode), `jet-design.jpg` (Rechnungs-PDF) - `druckkalkulation_config.yaml` — auto-created/auto-saved state (in .gitignore) - `proxmox-setup.sh` — Proxmox LXC-Ersteinrichtung - `proxmox-update.sh` — Proxmox LXC-Update @@ -100,4 +102,14 @@ Kein Test, Lint, Typecheck oder CI vorhanden. README.md und AGENTS.md enthalten `_migriere()` in eine einzelne Position und entfernt die Altfelder. - **Saeamtliche UI-Texte sind Deutsch** — Labels, Fehlermeldungen, Rechnungsinhalte. - Nur `.venv/`, `druckkalkulation_config.yaml` und `static/logo.*` werden ignoriert. + `static/img/logo/` ist davon nicht betroffen und wird versioniert. +- Das Rechnungslogo liefert `logo_datei()`: hochgeladenes Logo vor + `STANDARD_LOGO`, und erst wenn beide Dateien fehlen, setzt der PDF-Kopf + den Namen als Text. Nie direkt `config['logo']` fuer die Ausgabe lesen. +- Die Wortmarke ist im SVG fest eingefaerbt. Deshalb stehen im Kopf beide + Varianten im Markup und `static/style.css` blendet ueber + `[data-bs-theme="dark"]` die passende ein -- `toggleDarkMode()` laedt die + Seite nicht neu, eine serverseitige Auswahl waere danach falsch. Am + `navbar-brand` darf `navbar-brand-autodark` nicht stehen: Tabler invertiert + damit Bilder im Dark Mode und wuerde die weisse Variante schwarz faerben. - `3dDruckKalkulator.py` ist die alte Tkinter-Version und wird nicht mehr verwendet (nicht im Tracking). diff --git a/README.md b/README.md index f879915..5e0b9ae 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,8 @@ sich ueber `HOST` und `PORT` ueberschreiben. - *Regelbesteuert* — MwSt. mit 19 % oder 7 % - **Rechnungspflichtangaben** nach §14 UStG (Steuernummer/USt-IdNr., Leistungsdatum) — nur in den beiden Unternehmer-Modi -- **Logo-Upload** (PNG/JPEG/WebP) für die Rechnung +- **JET-Design-Wortmarke** im Seitenkopf (SVG, hell/dunkel) und auf der + Rechnung (JPEG). Ein eigenes **Logo-Upload** (PNG/JPEG/WebP) ersetzt sie. ## Installation auf Proxmox (LXC-Container) @@ -151,3 +152,5 @@ druckkalkulation_projekte.yaml # Gespeicherte Projekte (ignoriert) - Alle UI-Texte sind Deutsch - Die YAML-Config wird automatisch erstellt und bei jedem Tastendruck gespeichert - `druckkalkulation_config.yaml` und `static/logo.*` sind in `.gitignore` ausgeschlossen +- `static/img/logo/` gehört dagegen ins Repo: die beiden SVG-Varianten für den + Seitenkopf und `jet-design.jpg` für den Rechnungsdruck (fpdf2 setzt nur Pixelbilder) diff --git a/app.py b/app.py index c79bb95..b3e1bc4 100644 --- a/app.py +++ b/app.py @@ -118,6 +118,20 @@ def as_stueckzahl(value): return max(1, zahl) + +def logo_datei(config): + """Pfad des Rechnungslogos relativ zu static/. + + Ein hochgeladenes Logo hat Vorrang, sonst greift die mitgelieferte + Wortmarke. Fehlen beide Dateien, kommt '' zurueck und der PDF-Kopf + setzt den Firmennamen als Text. + """ + for name in (config.get('logo', ''), STANDARD_LOGO): + if name and os.path.exists(os.path.join('static', name)): + return name + return '' + + def pdf_text(value): """Macht beliebigen Text fuer die latin-1-Kernfonts von fpdf sicher. @@ -147,6 +161,11 @@ MAX_PROJEKTE = 500 LOGO_EXTS = ('png', 'jpg', 'webp') +# Mitgelieferte JET-Design-Wortmarke fuer den Rechnungskopf. Aus der +# SVG-Vorlage des Shops gerastert, weil fpdf2 nur Pixelbilder setzt. +# Greift, solange kein eigenes Logo hochgeladen wurde. +STANDARD_LOGO = 'img/logo/jet-design.jpg' + # Obergrenze, damit ein fehlerhafter Client die Config nicht aufblaeht. MAX_POSITIONEN = 50 @@ -589,7 +608,8 @@ def index(): def settings(): """Einstellungsseite fuer Druckerabschreibung, Arbeitskosten und Marge.""" config = load_config() - return render_template('settings.html', config=config) + return render_template('settings.html', config=config, + logo_anzeige=logo_datei(config)) @app.route('/calculate', methods=['POST']) @@ -843,9 +863,9 @@ def invoice_pdf(): col_w = 45 # Logo rechts oben - logo_name = config.get('logo', '') + logo_name = logo_datei(config) logo_path = os.path.join('static', logo_name) if logo_name else '' - if logo_name and os.path.exists(logo_path): + if logo_name: pdf.image(logo_path, x=175, y=12, w=20) img_w, img_h = image_dimensions(logo_path) if img_w and img_h: diff --git a/static/img/logo/jet-design-weiss.svg b/static/img/logo/jet-design-weiss.svg new file mode 100644 index 0000000..1a44c71 --- /dev/null +++ b/static/img/logo/jet-design-weiss.svg @@ -0,0 +1,7 @@ + + Jet-Design + + + diff --git a/static/img/logo/jet-design.jpg b/static/img/logo/jet-design.jpg new file mode 100644 index 0000000..0c2d602 Binary files /dev/null and b/static/img/logo/jet-design.jpg differ diff --git a/static/img/logo/jet-design.svg b/static/img/logo/jet-design.svg new file mode 100644 index 0000000..e7bb54a --- /dev/null +++ b/static/img/logo/jet-design.svg @@ -0,0 +1,7 @@ + + Jet-Design + + + diff --git a/static/style.css b/static/style.css index b5de207..8614fef 100644 --- a/static/style.css +++ b/static/style.css @@ -11,3 +11,25 @@ white-space: pre; overflow-x: auto; } + +/* Wortmarke im Kopf. Die Schrift ist im SVG fest eingefaerbt, deshalb + liegen beide Varianten im Markup und die zum Theme passende wird + eingeblendet -- der Dark-Mode-Schalter tauscht nur das Attribut am + , ohne die Seite neu zu laden. */ +.marke { + height: 40px; + width: auto; + display: block; +} + +.marke-dunkel { + display: none; +} + +[data-bs-theme="dark"] .marke-hell { + display: none; +} + +[data-bs-theme="dark"] .marke-dunkel { + display: block; +} diff --git a/templates/index.html b/templates/index.html index c7c1b34..08a8149 100644 --- a/templates/index.html +++ b/templates/index.html @@ -16,8 +16,9 @@