Compare commits
No commits in common. "main" and "v1.0.0" have entirely different histories.
8098 changed files with 1042617 additions and 8960 deletions
|
|
@ -18,10 +18,9 @@ APP_MAINTENANCE_DRIVER=file
|
|||
BCRYPT_ROUNDS=12
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_STACK=daily
|
||||
LOG_STACK=single
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=warning
|
||||
LOG_DAILY_DAYS=14
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
44
.gitignore
vendored
44
.gitignore
vendored
|
|
@ -1,44 +0,0 @@
|
|||
# ── Dependencies ──
|
||||
/node_modules/
|
||||
/vendor/
|
||||
/schneespur/node_modules/
|
||||
/schneespur/vendor/
|
||||
|
||||
# ── Local env (keep .env.example tracked) ──
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# ── Laravel runtime ──
|
||||
/schneespur/storage/logs/*.log
|
||||
/schneespur/storage/framework/cache/*
|
||||
/schneespur/storage/framework/sessions/*
|
||||
/schneespur/storage/framework/views/*
|
||||
/schneespur/storage/testing/
|
||||
|
||||
# ── Build artifacts ──
|
||||
/schneespur/public/build/
|
||||
/schneespur/public/hot
|
||||
/release/
|
||||
|
||||
# ── Internal dev files (not part of distributable app) ──
|
||||
/build.sh
|
||||
/moduldoku.md
|
||||
/package-lock.json
|
||||
|
||||
# ── Test caches ──
|
||||
.phpunit.result.cache
|
||||
.phpunit.cache/
|
||||
|
||||
# ── IDE / OS ──
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# ── Local tooling ──
|
||||
.gsd
|
||||
.gsd-id
|
||||
.mcp.json
|
||||
.bg-shell/
|
||||
|
|
@ -27,9 +27,9 @@ Diese Anleitung beschreibt die Installation von Schneespur auf einem klassischen
|
|||
| MySQL | 5.7 | 8.0+ |
|
||||
| MariaDB (alternativ) | 10.3 | 10.6+ |
|
||||
|
||||
### Benötigte PHP-Erweiterungen
|
||||
### Benoetigte PHP-Erweiterungen
|
||||
|
||||
**Pflicht** (Installation schlägt ohne diese fehl):
|
||||
**Pflicht** (Installation schlaegt ohne diese fehl):
|
||||
|
||||
- `pdo_mysql`
|
||||
- `gd`
|
||||
|
|
@ -89,9 +89,9 @@ Das Document-Root (manchmal auch „Webroot" oder „Stammverzeichnis" genannt)
|
|||
|
||||
**Beispiel:** Wenn Sie die Dateien nach `/schneespur/` hochgeladen haben, setzen Sie das Document-Root auf `/schneespur/public/`.
|
||||
|
||||
So geht das bei gängigen Hostern:
|
||||
So geht das bei gaengigen Hostern:
|
||||
|
||||
- **Strato:** Paket-Verwaltung → Domain-Verwaltung → Umleitung/Ziel → Pfad ändern
|
||||
- **Strato:** Paket-Verwaltung → Domain-Verwaltung → Umleitung/Ziel → Pfad aendern
|
||||
- **IONOS:** Hosting → Domains → Document-Root bearbeiten
|
||||
- **All-Inkl:** Domain-Einstellungen → Ordnerzuordnung
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ So geht das bei gängigen Hostern:
|
|||
|
||||
## 4. Datenbank anlegen
|
||||
|
||||
Erstellen Sie über das Verwaltungspanel Ihres Hosters eine neue MySQL-Datenbank. Notieren Sie sich:
|
||||
Erstellen Sie ueber das Verwaltungspanel Ihres Hosters eine neue MySQL-Datenbank. Notieren Sie sich:
|
||||
|
||||
- **Host** (z. B. `localhost` oder `rdbms.strato.de`)
|
||||
- **Port** (Standard: `3306`)
|
||||
|
|
@ -109,27 +109,27 @@ Erstellen Sie über das Verwaltungspanel Ihres Hosters eine neue MySQL-Datenbank
|
|||
- **Benutzername**
|
||||
- **Passwort**
|
||||
|
||||
Diese Daten benötigen Sie im nächsten Schritt.
|
||||
Diese Daten benoetigen Sie im naechsten Schritt.
|
||||
|
||||
---
|
||||
|
||||
## 5. Installations-Assistent
|
||||
|
||||
Öffnen Sie Ihre Domain im Browser. Schneespur erkennt automatisch, dass noch keine Installation vorliegt, und startet den Assistenten.
|
||||
Oeffnen Sie Ihre Domain im Browser. Schneespur erkennt automatisch, dass noch keine Installation vorliegt, und startet den Assistenten.
|
||||
|
||||
### Schritt 1: Willkommen
|
||||
|
||||
Der Assistent prüft die Grundvoraussetzungen und erzeugt die Konfigurationsdatei (`.env`) sowie den Anwendungsschlüssel (`APP_KEY`).
|
||||
Der Assistent prueft die Grundvoraussetzungen und erzeugt die Konfigurationsdatei (`.env`) sowie den Anwendungsschluessel (`APP_KEY`).
|
||||
|
||||
### Schritt 2: Datenbank
|
||||
|
||||
Geben Sie die Zugangsdaten aus Schritt 4 ein. Der Assistent testet die Verbindung, bevor er fortfährt.
|
||||
Geben Sie die Zugangsdaten aus Schritt 4 ein. Der Assistent testet die Verbindung, bevor er fortfaehrt.
|
||||
|
||||
> Falls die `.env`-Datei nicht beschreibbar ist (selten bei Shared-Hosting), zeigt der Assistent eine Anleitung zum manuellen Bearbeiten per FTP an.
|
||||
|
||||
### Schritt 3: Systemcheck
|
||||
|
||||
Der Assistent prüft PHP-Version, Erweiterungen und Schreibrechte auf wichtige Verzeichnisse (`storage/`, `bootstrap/cache/`). Fehlende Erweiterungen werden als Pflicht oder Empfehlung markiert.
|
||||
Der Assistent prueft PHP-Version, Erweiterungen und Schreibrechte auf wichtige Verzeichnisse (`storage/`, `bootstrap/cache/`). Fehlende Erweiterungen werden als Pflicht oder Empfehlung markiert.
|
||||
|
||||
### Schritt 4: Datenbank-Migration
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ Legen Sie fest:
|
|||
|
||||
### Schritt 6: Speicher & Caches
|
||||
|
||||
Der Assistent erstellt die Verknüpfung zum öffentlichen Speicher (`storage:link`) und baut Caches auf. Falls die Verknüpfung auf Ihrem Hoster nicht funktioniert, wird eine Anleitung zum manuellen Anlegen per FTP angezeigt.
|
||||
Der Assistent erstellt die Verknuepfung zum oeffentlichen Speicher (`storage:link`) und baut Caches auf. Falls die Verknuepfung auf Ihrem Hoster nicht funktioniert, wird eine Anleitung zum manuellen Anlegen per FTP angezeigt.
|
||||
|
||||
### Schritt 7: Admin-Konto
|
||||
|
||||
|
|
@ -153,17 +153,17 @@ Erstellen Sie Ihr Administrator-Konto (Name, E-Mail, Passwort mit mindestens 8 Z
|
|||
|
||||
### Schritt 8: E-Mail-Konfiguration (optional)
|
||||
|
||||
Richten Sie SMTP-Versand ein, damit Schneespur Benachrichtigungen senden kann. Dieser Schritt kann übersprungen und später in den Einstellungen nachgeholt werden.
|
||||
Richten Sie SMTP-Versand ein, damit Schneespur Benachrichtigungen senden kann. Dieser Schritt kann uebersprungen und spaeter in den Einstellungen nachgeholt werden.
|
||||
|
||||
### Fertig
|
||||
|
||||
Nach Abschluss sehen Sie eine Zusammenfassung. Sie können sich jetzt mit Ihren Admin-Zugangsdaten anmelden.
|
||||
Nach Abschluss sehen Sie eine Zusammenfassung. Sie koennen sich jetzt mit Ihren Admin-Zugangsdaten anmelden.
|
||||
|
||||
---
|
||||
|
||||
## 6. Cron-Job einrichten
|
||||
|
||||
Schneespur benötigt einen Cron-Job, der einmal pro Minute den Laravel-Scheduler ausführt. Dieser verarbeitet die Auftragswarteschlange (z. B. Wetterdaten abrufen, Benachrichtigungen senden).
|
||||
Schneespur benoetigt einen Cron-Job, der einmal pro Minute den Laravel-Scheduler ausfuehrt. Dieser verarbeitet die Auftragswarteschlange (z. B. Wetterdaten abrufen, Benachrichtigungen senden).
|
||||
|
||||
### Cron-Befehl
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ Schneespur benötigt einen Cron-Job, der einmal pro Minute den Laravel-Scheduler
|
|||
* * * * * /usr/local/bin/php /pfad/zu/schneespur/artisan schedule:run >> /dev/null 2>&1
|
||||
```
|
||||
|
||||
> **Wichtig:** Ersetzen Sie `/pfad/zu/schneespur/` durch den tatsächlichen Pfad auf Ihrem Webspace und `/usr/local/bin/php` durch den PHP-Pfad Ihres Hosters (häufig auch `/usr/bin/php` oder `/usr/bin/php8.3`).
|
||||
> **Wichtig:** Ersetzen Sie `/pfad/zu/schneespur/` durch den tatsaechlichen Pfad auf Ihrem Webspace und `/usr/local/bin/php` durch den PHP-Pfad Ihres Hosters (haeufig auch `/usr/bin/php` oder `/usr/bin/php8.3`).
|
||||
|
||||
### So richten Sie den Cron-Job ein
|
||||
|
||||
|
|
@ -179,13 +179,13 @@ Schneespur benötigt einen Cron-Job, der einmal pro Minute den Laravel-Scheduler
|
|||
- **IONOS:** Hosting → Cron-Jobs → Cronjob anlegen
|
||||
- **All-Inkl:** Tools → Cronjobs → Neuer Cronjob
|
||||
|
||||
Stellen Sie die Ausführung auf **jede Minute** oder das kürzeste verfügbare Intervall.
|
||||
Stellen Sie die Ausfuehrung auf **jede Minute** oder das kuerzeste verfuegbare Intervall.
|
||||
|
||||
### Warum ist der Cron-Job nötig?
|
||||
### Warum ist der Cron-Job noetig?
|
||||
|
||||
Ohne Cron-Job werden keine Hintergrundaufgaben verarbeitet:
|
||||
|
||||
- Wetterdaten werden nicht automatisch zu Einsätzen hinzugefügt
|
||||
- Wetterdaten werden nicht automatisch zu Einsaetzen hinzugefuegt
|
||||
- E-Mail-Benachrichtigungen werden nicht versendet
|
||||
- Geplante Aufgaben laufen nicht
|
||||
|
||||
|
|
@ -193,18 +193,18 @@ Ohne Cron-Job werden keine Hintergrundaufgaben verarbeitet:
|
|||
|
||||
## 7. OwnTracks einrichten
|
||||
|
||||
OwnTracks ist die GPS-Tracking-App, mit der Ihre Fahrer die Einsätze aufzeichnen. Jeder Fahrer benötigt die App auf seinem Smartphone.
|
||||
OwnTracks ist die GPS-Tracking-App, mit der Ihre Fahrer die Einsaetze aufzeichnen. Jeder Fahrer benoetigt die App auf seinem Smartphone.
|
||||
|
||||
### Kurzanleitung
|
||||
|
||||
1. **App installieren:** OwnTracks aus dem App Store (iOS) oder Google Play Store (Android) herunterladen.
|
||||
2. **Zugangsdaten erzeugen:** Melden Sie sich als Admin in Schneespur an, öffnen Sie die Fahrer-Übersicht und klicken Sie beim jeweiligen Fahrer auf „Zugangsdaten". Schneespur erzeugt automatisch Benutzername und Passwort.
|
||||
2. **Zugangsdaten erzeugen:** Melden Sie sich als Admin in Schneespur an, oeffnen Sie die Fahrer-Uebersicht und klicken Sie beim jeweiligen Fahrer auf „Zugangsdaten". Schneespur erzeugt automatisch Benutzername und Passwort.
|
||||
3. **QR-Code scannen:** Auf der Zugangsdaten-Seite wird ein QR-Code angezeigt. Der Fahrer scannt diesen mit der OwnTracks-App, und die Verbindung wird automatisch konfiguriert.
|
||||
4. **Manuell konfigurieren** (falls QR-Code nicht funktioniert):
|
||||
- Modus: **HTTP**
|
||||
- URL: `https://ihre-domain.de/api/owntracks/report`
|
||||
- Benutzername und Passwort: wie in Schneespur angezeigt
|
||||
5. **Testen:** Öffnen Sie in Schneespur unter „OwnTracks" die Übersicht. Sobald der Fahrer die App startet, sollte dort ein grüner Status erscheinen.
|
||||
5. **Testen:** Oeffnen Sie in Schneespur unter „OwnTracks" die Uebersicht. Sobald der Fahrer die App startet, sollte dort ein gruener Status erscheinen.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -213,17 +213,17 @@ OwnTracks ist die GPS-Tracking-App, mit der Ihre Fahrer die Einsätze aufzeichne
|
|||
### Vor dem Update
|
||||
|
||||
1. Erstellen Sie ein Backup (siehe [Backup](#9-backup)).
|
||||
2. Aktivieren Sie den Wartungsmodus: Öffnen Sie `https://ihre-domain.de/down` im Browser oder führen Sie `php artisan down` per SSH/Cron aus.
|
||||
2. Aktivieren Sie den Wartungsmodus: Oeffnen Sie `https://ihre-domain.de/down` im Browser oder fuehren Sie `php artisan down` per SSH/Cron aus.
|
||||
|
||||
### Update durchführen
|
||||
### Update durchfuehren
|
||||
|
||||
1. Laden Sie das neue Release herunter.
|
||||
2. Überschreiben Sie alle Dateien per FTP. Überspringen Sie dabei **nicht** die `.env`-Datei — diese wird beim Upload ohnehin nicht überschrieben, solange Sie nur die Release-Dateien hochladen.
|
||||
3. Führen Sie die Datenbank-Migration aus. Dafür gibt es zwei Wege:
|
||||
- **Ueber den Browser:** Öffnen Sie `https://ihre-domain.de/admin/settings` und prüfen Sie, ob eine Update-Migration angeboten wird.
|
||||
2. Ueberschreiben Sie alle Dateien per FTP. Ueberspringen Sie dabei **nicht** die `.env`-Datei — diese wird beim Upload ohnehin nicht ueberschrieben, solange Sie nur die Release-Dateien hochladen.
|
||||
3. Fuehren Sie die Datenbank-Migration aus. Dafuer gibt es zwei Wege:
|
||||
- **Ueber den Browser:** Oeffnen Sie `https://ihre-domain.de/admin/settings` und pruefen Sie, ob eine Update-Migration angeboten wird.
|
||||
- **Per Cron/SSH:** `php artisan migrate --force`
|
||||
4. Leeren Sie die Caches: `php artisan config:cache && php artisan view:cache`
|
||||
5. Deaktivieren Sie den Wartungsmodus: Öffnen Sie `https://ihre-domain.de/up` oder führen Sie `php artisan up` aus.
|
||||
5. Deaktivieren Sie den Wartungsmodus: Oeffnen Sie `https://ihre-domain.de/up` oder fuehren Sie `php artisan up` aus.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -239,9 +239,9 @@ OwnTracks ist die GPS-Tracking-App, mit der Ihre Fahrer die Einsätze aufzeichne
|
|||
|
||||
### Empfohlener Rhythmus
|
||||
|
||||
- **Datenbank:** wöchentlich oder vor jedem Update
|
||||
- **Datenbank:** woechentlich oder vor jedem Update
|
||||
- **Dateien:** vor jedem Update
|
||||
- **Konfiguration:** nach jeder Änderung und vor Updates
|
||||
- **Konfiguration:** nach jeder Aenderung und vor Updates
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -249,47 +249,47 @@ OwnTracks ist die GPS-Tracking-App, mit der Ihre Fahrer die Einsätze aufzeichne
|
|||
|
||||
### Installations-Assistent erscheint nicht
|
||||
|
||||
- Prüfen Sie, ob das Document-Root korrekt auf `/public` zeigt.
|
||||
- Prüfen Sie, ob die `.htaccess`-Datei im `public/`-Ordner vorhanden ist.
|
||||
- Pruefen Sie, ob das Document-Root korrekt auf `/public` zeigt.
|
||||
- Pruefen Sie, ob die `.htaccess`-Datei im `public/`-Ordner vorhanden ist.
|
||||
- Stellen Sie sicher, dass `mod_rewrite` (Apache) aktiviert ist.
|
||||
|
||||
### Datenbankverbindung schlägt fehl
|
||||
### Datenbankverbindung schlaegt fehl
|
||||
|
||||
- Prüfen Sie Host, Port, Datenbankname, Benutzername und Passwort.
|
||||
- Pruefen Sie Host, Port, Datenbankname, Benutzername und Passwort.
|
||||
- Bei Strato lautet der Host oft `rdbms.strato.de`, nicht `localhost`.
|
||||
- Stellen Sie sicher, dass der Datenbankbenutzer Zugriff auf die angegebene Datenbank hat.
|
||||
|
||||
### Seite zeigt „500 Internal Server Error"
|
||||
|
||||
- Prüfen Sie die Schreibrechte: `storage/` und `bootstrap/cache/` müssen beschreibbar sein (Rechte 755 oder 775).
|
||||
- Pruefen Sie die Schreibrechte: `storage/` und `bootstrap/cache/` muessen beschreibbar sein (Rechte 755 oder 775).
|
||||
- Schauen Sie in `storage/logs/laravel.log` nach der Fehlermeldung.
|
||||
|
||||
### GPS-Daten kommen nicht an
|
||||
|
||||
- Prüfen Sie in OwnTracks, ob der Modus auf „HTTP" steht (nicht MQTT).
|
||||
- Prüfen Sie die URL: `https://ihre-domain.de/api/owntracks/report`
|
||||
- Prüfen Sie Benutzername und Passwort in der OwnTracks-App.
|
||||
- Öffnen Sie die OwnTracks-Übersicht in Schneespur — dort wird der letzte Verbindungsstatus angezeigt.
|
||||
- Pruefen Sie in OwnTracks, ob der Modus auf „HTTP" steht (nicht MQTT).
|
||||
- Pruefen Sie die URL: `https://ihre-domain.de/api/owntracks/report`
|
||||
- Pruefen Sie Benutzername und Passwort in der OwnTracks-App.
|
||||
- Oeffnen Sie die OwnTracks-Uebersicht in Schneespur — dort wird der letzte Verbindungsstatus angezeigt.
|
||||
|
||||
### Wetterdaten fehlen bei Einsätzen
|
||||
### Wetterdaten fehlen bei Einsaetzen
|
||||
|
||||
- Stellen Sie sicher, dass der Cron-Job läuft (siehe [Cron-Job einrichten](#6-cron-job-einrichten)).
|
||||
- Wetterdaten werden über Open-Meteo abgerufen. Prüfen Sie, ob Ihr Server ausgehende HTTPS-Verbindungen erlaubt.
|
||||
- Stellen Sie sicher, dass der Cron-Job laeuft (siehe [Cron-Job einrichten](#6-cron-job-einrichten)).
|
||||
- Wetterdaten werden ueber Open-Meteo abgerufen. Pruefen Sie, ob Ihr Server ausgehende HTTPS-Verbindungen erlaubt.
|
||||
|
||||
### E-Mails werden nicht versendet
|
||||
|
||||
- Prüfen Sie die SMTP-Einstellungen unter Einstellungen → E-Mail.
|
||||
- Pruefen Sie die SMTP-Einstellungen unter Einstellungen → E-Mail.
|
||||
- Nutzen Sie die Test-E-Mail-Funktion in den Einstellungen.
|
||||
- Schauen Sie in `storage/logs/laravel.log` nach Fehlermeldungen.
|
||||
|
||||
### Cron-Job funktioniert nicht
|
||||
|
||||
- Prüfen Sie den PHP-Pfad: Führen Sie `which php` aus oder fragen Sie Ihren Hoster.
|
||||
- Prüfen Sie den Pfad zur `artisan`-Datei.
|
||||
- Pruefen Sie den PHP-Pfad: Fuehren Sie `which php` aus oder fragen Sie Ihren Hoster.
|
||||
- Pruefen Sie den Pfad zur `artisan`-Datei.
|
||||
- Testen Sie den Befehl manuell: `php /pfad/zu/schneespur/artisan schedule:run`
|
||||
|
||||
---
|
||||
|
||||
## Hilfe
|
||||
|
||||
Bei Fragen nutzen Sie die integrierte Hilfe im Admin-Bereich (Menü → Hilfe) oder erstellen Sie ein Issue im GitHub-Repository.
|
||||
Bei Fragen nutzen Sie die integrierte Hilfe im Admin-Bereich (Menue → Hilfe) oder erstellen Sie ein Issue im GitHub-Repository.
|
||||
|
|
|
|||
27
README.md
27
README.md
|
|
@ -1,5 +1,5 @@
|
|||
<p align="center">
|
||||
<img src="schneespur/public/pwa-icon-512x512.png" alt="Schneespur" width="120">
|
||||
<img src="public/pwa-icon-512x512.png" alt="Schneespur" width="120">
|
||||
</p>
|
||||
|
||||
<h1 align="center">Schneespur</h1>
|
||||
|
|
@ -9,39 +9,34 @@
|
|||
GPS-Tracks · Wetterdaten · Fotos · rechtsfester Einsatznachweis
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://schneespur.de">schneespur.de</a> ·
|
||||
<a href="https://wintertrace.com">wintertrace.com</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#english">English</a> ·
|
||||
<a href="INSTALL.de.md">Installation (DE)</a> ·
|
||||
<a href="INSTALL.en.md">Installation (EN)</a> ·
|
||||
<a href="https://schneespur.de/download/">Download</a>
|
||||
<a href="https://jenni.noschmarrn.dev">Download</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## Was ist Schneespur?
|
||||
|
||||
Schneespur dokumentiert Räum- und Streueinsätze für kleine Winterdienst-Betriebe — vollständig, automatisch und rechtssicher. Die Software läuft auf jedem günstigen Shared-Webhosting (Strato, IONOS, All-Inkl, ...) und braucht weder SSH noch Docker.
|
||||
Schneespur dokumentiert Raeum- und Streueinsaetze fuer kleine Winterdienst-Betriebe — vollstaendig, automatisch und rechtssicher. Die Software laeuft auf jedem guenstigen Shared-Webhosting (Strato, IONOS, All-Inkl, ...) und braucht weder SSH noch Docker.
|
||||
|
||||
**Kernversprechen:** Wenn ein Passant auf einer gestreuten Fläche ausrutscht und der Betreiber nachweisen muss, dass er seiner Verkehrssicherungspflicht nachgekommen ist, liefert Schneespur den Beleg — mit GPS-Track, Wetterlage, Fotos und Zeitstempeln.
|
||||
**Kernversprechen:** Wenn ein Passant auf einer gestreuten Flaeche ausrutscht und der Betreiber nachweisen muss, dass er seiner Verkehrssicherungspflicht nachgekommen ist, liefert Schneespur den Beleg — mit GPS-Track, Wetterlage, Fotos und Zeitstempeln.
|
||||
|
||||
### Funktionen
|
||||
|
||||
- **GPS-Tracking** via [OwnTracks](https://owntracks.org)-App (iOS/Android) — kein eigener Tracking-Client nötig
|
||||
- **GPS-Tracking** via [OwnTracks](https://owntracks.org)-App (iOS/Android) — kein eigener Tracking-Client noetig
|
||||
- **Automatische Wetterdokumentation** — Temperatur, Niederschlag, Wind, Schneelage zum Einsatzzeitpunkt (Open-Meteo, BrightSky, Met.no)
|
||||
- **Foto-Dokumentation** — Bilder direkt aus der Fahrer-App hochladen
|
||||
- **PDF-Einsatznachweise** — einzeln oder als Sammelreport pro Kunde und Zeitraum
|
||||
- **Kundenportal** — Kunden können ihre Einsätze selbst einsehen
|
||||
- **Kundenportal** — Kunden koennen ihre Einsaetze selbst einsehen
|
||||
- **Fahrer-App (PWA)** — funktioniert offline, synchronisiert automatisch bei Verbindung
|
||||
- **Kunden- und Objektverwaltung** — mehrere Objekte pro Kunde, Zuordnung zu Einsätzen
|
||||
- **Kunden- und Objektverwaltung** — mehrere Objekte pro Kunde, Zuordnung zu Einsaetzen
|
||||
- **Fahrzeugverwaltung** — Fuhrpark mit Kennzeichen und Fahrzeugtyp
|
||||
- **DSGVO-konform** — Fahrer-Anonymisierung, Datenexport, konfigurierbare Aufbewahrungsfristen
|
||||
- **Automatische Updates** — kryptographisch signiert (Ed25519), ein Klick im Admin-Panel
|
||||
- **Modulsystem** — erweiterbar über Module aus dem Schneespur-Modulkatalog
|
||||
- **Modulsystem** — Erweiterbar ueber Module aus dem Schneespur-Modulkatalog
|
||||
|
||||
### Systemanforderungen
|
||||
|
||||
|
|
@ -55,10 +50,10 @@ Schneespur dokumentiert Räum- und Streueinsätze für kleine Winterdienst-Betri
|
|||
|
||||
### Schnellstart
|
||||
|
||||
1. [Download](https://schneespur.de/download/) der aktuellen Version (ZIP)
|
||||
1. [Download](https://jenni.noschmarrn.dev) der aktuellen Version (ZIP)
|
||||
2. ZIP entpacken und per FTP auf den Webserver laden
|
||||
3. Document Root auf den `public/`-Ordner setzen
|
||||
4. Im Browser die Domain aufrufen — der Installations-Assistent führt durch die Einrichtung
|
||||
4. Im Browser die Domain aufrufen — der Installations-Assistent fuehrt durch die Einrichtung
|
||||
|
||||
Detaillierte Anleitung: **[INSTALL.de.md](INSTALL.de.md)**
|
||||
|
||||
|
|
@ -115,7 +110,7 @@ Schneespur (German) / Wintertrace (international) is an open-source, self-hosted
|
|||
|
||||
### Quick Start
|
||||
|
||||
1. [Download](https://wintertrace.com/download/) the latest release (ZIP)
|
||||
1. [Download](https://jenni.noschmarrn.dev) the latest release (ZIP)
|
||||
2. Extract and upload via FTP to your web server
|
||||
3. Set the document root to the `public/` directory
|
||||
4. Open the domain in your browser — the installation wizard guides you through setup
|
||||
|
|
|
|||
1
VERSION
Normal file
1
VERSION
Normal file
|
|
@ -0,0 +1 @@
|
|||
1.0.0
|
||||
|
|
@ -4,7 +4,6 @@ namespace App\Http\Controllers\Admin;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Module;
|
||||
use App\Services\ModuleManager;
|
||||
use App\Services\SchneespurModuleClient;
|
||||
use App\Services\SchneespurModuleInstaller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
|
@ -23,7 +22,12 @@ class AdminModuleController extends Controller
|
|||
|
||||
try {
|
||||
$catalog = $client->fetchCatalog();
|
||||
if ($catalog !== null) {
|
||||
$catalogModules = $catalog['modules'] ?? [];
|
||||
} else {
|
||||
$state = $client->loadState();
|
||||
$catalogModules = $state['installed'] ?? [];
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('schneespur-modules: catalog fetch failed in admin UI', [
|
||||
'error' => $e->getMessage(),
|
||||
|
|
@ -54,7 +58,6 @@ class AdminModuleController extends Controller
|
|||
'download_url' => $catModule['download_url'] ?? null,
|
||||
'sha256' => $catModule['sha256'] ?? null,
|
||||
'size_bytes' => $catModule['size_bytes'] ?? null,
|
||||
'requires_permissions' => $catModule['requires_permissions'] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +80,6 @@ class AdminModuleController extends Controller
|
|||
'download_url' => null,
|
||||
'sha256' => null,
|
||||
'size_bytes' => null,
|
||||
'requires_permissions' => $this->resolveLocalPermissions($slug),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -228,16 +230,6 @@ class AdminModuleController extends Controller
|
|||
->with('success', __('modules.disabled', ['slug' => $slug]));
|
||||
}
|
||||
|
||||
private function resolveLocalPermissions(string $slug): array
|
||||
{
|
||||
try {
|
||||
$manager = app(ModuleManager::class);
|
||||
return $manager->getPermissions($slug);
|
||||
} catch (\Throwable) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(string $slug, SchneespurModuleInstaller $installer): RedirectResponse
|
||||
{
|
||||
$module = Module::where('slug', $slug)->first();
|
||||
|
|
@ -5,7 +5,6 @@ namespace App\Http\Controllers\Admin;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Setting;
|
||||
use App\Services\Extension\DashboardWidgetRegistry;
|
||||
use App\Services\Extension\FilterRegistry;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
|
||||
|
|
@ -18,10 +17,9 @@ class DashboardController extends Controller
|
|||
return redirect()->route('admin.dashboard');
|
||||
}
|
||||
|
||||
public function index(DashboardWidgetRegistry $widgetRegistry, FilterRegistry $filterRegistry): View
|
||||
public function index(DashboardWidgetRegistry $widgetRegistry): View
|
||||
{
|
||||
$widgets = $widgetRegistry->getWidgets();
|
||||
$widgets = $filterRegistry->apply('schneespur.dashboard.kpis', $widgets);
|
||||
|
||||
return view('admin.dashboard', compact('widgets'));
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\DsgvoOnboardingController;
|
||||
use App\Models\DsgvoConfirmation;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -19,7 +18,7 @@ class DsgvoAdminController extends Controller
|
|||
$version = (int) Setting::get('dsgvo_template_version', 1);
|
||||
|
||||
if ($markdown === null) {
|
||||
$markdown = view(DsgvoOnboardingController::resolveDefaultTemplateView())->render();
|
||||
$markdown = view('dsgvo.default-template')->render();
|
||||
}
|
||||
|
||||
$previewHtml = Str::markdown($this->replacePlaceholders($markdown), ['html_input' => 'strip']);
|
||||
|
|
@ -83,7 +82,25 @@ class DsgvoAdminController extends Controller
|
|||
|
||||
private function replacePlaceholders(string $text): string
|
||||
{
|
||||
return dsgvo_apply_company_placeholders($text);
|
||||
$companyName = Setting::get('company_name', '');
|
||||
$street = Setting::get('company_street', '');
|
||||
$zip = Setting::get('company_zip', '');
|
||||
$city = Setting::get('company_city', '');
|
||||
$email = Setting::get('company_email', '');
|
||||
$dpo = Setting::get('dpo_contact', '');
|
||||
$dpoEmail = Setting::get('dpo_email', '');
|
||||
|
||||
$address = trim("$street, $zip $city", ', ');
|
||||
|
||||
$replacements = [
|
||||
'[Firmenname eintragen]' => $companyName ?: '[Firmenname eintragen]',
|
||||
'[Adresse eintragen]' => $address ?: '[Adresse eintragen]',
|
||||
'[E-Mail-Adresse eintragen]' => $email ?: '[E-Mail-Adresse eintragen]',
|
||||
'[DPO-E-Mail-Adresse eintragen]' => $dpoEmail ?: '[DPO-E-Mail-Adresse eintragen]',
|
||||
'[Datenschutzbeauftragter / Ansprechpartner eintragen]' => $dpo ?: '[Datenschutzbeauftragter / Ansprechpartner eintragen]',
|
||||
];
|
||||
|
||||
return str_replace(array_keys($replacements), array_values($replacements), $text);
|
||||
}
|
||||
|
||||
public function showConfirmation(int $id): View
|
||||
|
|
@ -66,22 +66,32 @@ class DsgvoOnboardingController extends Controller
|
|||
$version = (int) Setting::get('dsgvo_template_version', 1);
|
||||
|
||||
if ($text === null) {
|
||||
$text = view(self::resolveDefaultTemplateView())->render();
|
||||
$text = view('dsgvo.default-template')->render();
|
||||
}
|
||||
|
||||
return [$text, $version];
|
||||
}
|
||||
|
||||
public static function resolveDefaultTemplateView(): string
|
||||
{
|
||||
$locale = app()->getLocale();
|
||||
$localized = "dsgvo.default-template-{$locale}";
|
||||
|
||||
return view()->exists($localized) ? $localized : 'dsgvo.default-template';
|
||||
}
|
||||
|
||||
private function replacePlaceholders(string $text): string
|
||||
{
|
||||
return dsgvo_apply_company_placeholders($text);
|
||||
$companyName = Setting::get('company_name', '');
|
||||
$street = Setting::get('company_street', '');
|
||||
$zip = Setting::get('company_zip', '');
|
||||
$city = Setting::get('company_city', '');
|
||||
$email = Setting::get('company_email', '');
|
||||
$dpo = Setting::get('dpo_contact', '');
|
||||
$dpoEmail = Setting::get('dpo_email', '');
|
||||
|
||||
$address = trim("$street, $zip $city", ', ');
|
||||
|
||||
$replacements = [
|
||||
'[Firmenname eintragen]' => $companyName ?: '[Firmenname eintragen]',
|
||||
'[Adresse eintragen]' => $address ?: '[Adresse eintragen]',
|
||||
'[E-Mail-Adresse eintragen]' => $email ?: '[E-Mail-Adresse eintragen]',
|
||||
'[DPO-E-Mail-Adresse eintragen]' => $dpoEmail ?: '[DPO-E-Mail-Adresse eintragen]',
|
||||
'[Datenschutzbeauftragter / Ansprechpartner eintragen]' => $dpo ?: '[Datenschutzbeauftragter / Ansprechpartner eintragen]',
|
||||
];
|
||||
|
||||
return str_replace(array_keys($replacements), array_values($replacements), $text);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,17 +27,6 @@ class InstallerController extends Controller
|
|||
private InstallLockManager $lockManager,
|
||||
) {}
|
||||
|
||||
// --- Locale switcher (works on any installer step) ---
|
||||
|
||||
public function switchLocale(Request $request, string $locale): RedirectResponse
|
||||
{
|
||||
if (in_array($locale, ['de', 'en'], true)) {
|
||||
$request->session()->put('installer_locale', $locale);
|
||||
}
|
||||
|
||||
return redirect($request->headers->get('referer') ?: route('install.welcome'));
|
||||
}
|
||||
|
||||
// --- Step 1: Welcome ---
|
||||
|
||||
public function showWelcome(Request $request): View
|
||||
|
|
@ -129,7 +118,7 @@ class InstallerController extends Controller
|
|||
{
|
||||
if ($this->preflightChecker->hasCriticalFailures()) {
|
||||
return redirect()->route('install.preflight')
|
||||
->withErrors(['preflight' => __('install.preflight_has_failures')]);
|
||||
->withErrors(['preflight' => 'Kritische Voraussetzungen nicht erfüllt.']);
|
||||
}
|
||||
|
||||
return redirect()->route('install.database');
|
||||
|
|
@ -19,14 +19,6 @@ class StoreCustomerObjectRequest extends FormRequest
|
|||
'price_amount' => str_replace(',', '.', $this->price_amount),
|
||||
]);
|
||||
}
|
||||
|
||||
// notify_recipients is a mode enum consumed as customer|object|both
|
||||
// (see SendJobCompletedNotification / SendCustomerReportEmail).
|
||||
// Fall back to the DB default when the field is missing or empty
|
||||
// so the NOT NULL column never receives a null value.
|
||||
if (! $this->filled('notify_recipients')) {
|
||||
$this->merge(['notify_recipients' => 'customer']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -52,7 +44,7 @@ class StoreCustomerObjectRequest extends FormRequest
|
|||
'lon' => ['nullable', 'numeric', 'between:-180,180'],
|
||||
'auto_notify_email' => ['boolean'],
|
||||
'notification_email' => ['nullable', 'required_if:auto_notify_email,1', 'email', 'max:200'],
|
||||
'notify_recipients' => ['required', 'in:customer,object,both'],
|
||||
'notify_recipients' => ['nullable', 'string', 'max:1000'],
|
||||
];
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue