urlRoot wird einmalig aus dem src-Attribut des globalnotify-Scripts abgeleitet, damit AJAX-Calls unabhängig vom Installationspfad funktionieren (z.B. /dolibarr/custom/... statt /custom/...). Behebt 404-Fehler bei Aktionen wie "Alle als gelesen markieren". Zusätzlich CLAUDE.md Projektdokumentation erstellt. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
124 lines
5 KiB
Markdown
124 lines
5 KiB
Markdown
# GlobalNotify - Dolibarr Custom Module
|
|
|
|
Globales Benachrichtigungssystem als schwebendes Widget (FAB) in der unteren linken Ecke.
|
|
Sammelt Alerts von allen Modulen (Cron-Fehler, Warnungen, Aktionen) und zeigt sie einheitlich an.
|
|
|
|
## Modul-Metadaten
|
|
|
|
- **Modul-Nummer**: 500100
|
|
- **Version**: 1.4.0
|
|
- **Autor**: Eduard Wisch / Data IT Solution
|
|
- **Hooks**: `main`, `toprightmenu`
|
|
- **Nur für Admins** (`$user->admin`)
|
|
|
|
## Projektstruktur
|
|
|
|
```
|
|
globalnotify/
|
|
admin/setup.php # Admin-Seite: Einstellungen + Übersicht
|
|
ajax/action.php # AJAX-Endpunkt für JS-Aktionen
|
|
class/
|
|
globalnotify.class.php # Kern-Klasse: Notification CRUD
|
|
actions_globalnotify.class.php # Hook-Klasse: Widget-Rendering + Cron-Checks
|
|
core/modules/modGlobalNotify.class.php # Modul-Deskriptor
|
|
css/globalnotify.css # Widget-Styles (Dark Mode Support)
|
|
js/globalnotify.js # Widget-Logik (Drag, AJAX, Sound)
|
|
langs/de_DE/globalnotify.lang # Deutsche Übersetzungen
|
|
langs/en_US/globalnotify.lang # Englische Übersetzungen
|
|
```
|
|
|
|
## Architektur
|
|
|
|
### Speicherung
|
|
Notifications werden als JSON-Arrays in `llx_const` gespeichert (NICHT in eigenen Tabellen):
|
|
- Schlüssel: `GLOBALNOTIFY_{MODULE}` (z.B. `GLOBALNOTIFY_CRON`, `GLOBALNOTIFY_BANKIMPORT`)
|
|
- Wert: JSON-Array mit Notification-Objekten
|
|
- Max 50 Notifications pro Modul
|
|
- Interne Settings: `GLOBALNOTIFY_CRON_LASTCHECK`, `GLOBALNOTIFY_CRON_CHECK_INTERVAL`
|
|
|
|
### Notification-Typen (Konstanten in GlobalNotify)
|
|
- `TYPE_ERROR` = `'error'` — Priorität 10
|
|
- `TYPE_ACTION` = `'action'` — Priorität 9
|
|
- `TYPE_WARNING` = `'warning'` — Priorität 7
|
|
- `TYPE_INFO` = `'info'` — Priorität 3
|
|
- `TYPE_SUCCESS` = `'success'`
|
|
|
|
### Notification-Objekt (JSON-Struktur)
|
|
```json
|
|
{
|
|
"id": "module_uniqid",
|
|
"module": "cron",
|
|
"type": "error",
|
|
"title": "Kurztitel",
|
|
"message": "Detailbeschreibung",
|
|
"action_url": "/cron/list.php",
|
|
"action_label": "Button-Text",
|
|
"priority": 10,
|
|
"user_id": 0,
|
|
"created": 1709000000,
|
|
"read": false
|
|
}
|
|
```
|
|
|
|
## API: Notifications senden (für andere Module)
|
|
|
|
```php
|
|
// Statische Helper (empfohlen):
|
|
dol_include_once('/globalnotify/class/globalnotify.class.php');
|
|
GlobalNotify::error('meinmodul', 'Titel', 'Nachricht', $actionUrl, $actionLabel);
|
|
GlobalNotify::warning('meinmodul', 'Titel', 'Nachricht');
|
|
GlobalNotify::info('meinmodul', 'Titel', 'Nachricht');
|
|
GlobalNotify::actionRequired('meinmodul', 'Titel', 'Nachricht', $actionUrl);
|
|
|
|
// Oder manuell mit voller Kontrolle:
|
|
$notify = new GlobalNotify($db);
|
|
$notify->addNotification($module, $type, $title, $message, $actionUrl, $actionLabel, $priority, $userId);
|
|
```
|
|
|
|
## AJAX-Endpunkt (`ajax/action.php`)
|
|
|
|
POST-Requests mit `action` Parameter:
|
|
- `dismiss` — Einzelne Notification als gelesen markieren (`id` Parameter)
|
|
- `delete` — Notification löschen (`id` Parameter)
|
|
- `markallread` — Alle als gelesen markieren
|
|
- `getall` — Alle ungelesenen abrufen
|
|
- `getcount` — Ungelesene Anzahl abrufen
|
|
|
|
Authentifizierung: Nur `$user->admin`, CSRF-Token über `TOKEN` JS-Variable.
|
|
|
|
## JavaScript (globalnotify.js)
|
|
|
|
- **`GlobalNotify.urlRoot`**: Wird beim Laden einmalig aus dem Script-src-Pfad ermittelt (z.B. `/dolibarr`), damit AJAX-Calls unabhängig vom Installationspfad funktionieren
|
|
- **Drag & Drop**: FAB ist verschiebbar, Position wird in `localStorage` gespeichert
|
|
- **Click vs. Drag**: Erkennung über Distanz (<5px) und Zeit (<200ms)
|
|
- **Auto-Refresh**: Alle 2 Minuten via `getcount` AJAX-Call
|
|
- **Sound**: Web Audio API Doppel-Ton bei neuen Notifications
|
|
- **Animationen**: Shake + Bounce bei neuen Notifications
|
|
|
|
## Automatische Cron-Prüfungen (in Hook-Klasse)
|
|
|
|
1. **Hängende Jobs**: `processing=1` seit >30 Min → `TYPE_ERROR`
|
|
2. **Verpasste Jobs**: `datenextrun` >2 Std. in der Vergangenheit → `TYPE_WARNING`
|
|
3. **Cleanup**: Notifications für deaktivierte Cronjobs werden automatisch als gelesen markiert
|
|
4. **Cache**: Prüfintervall konfigurierbar via `GLOBALNOTIFY_CRON_CHECK_INTERVAL` (Default: 60s, Min: 10s, Max: 3600s)
|
|
|
|
## Modul-spezifische Checks
|
|
|
|
- **BankImport**: Prüft `BankImportCron::getCronStatus()` auf `paused`, `tan_required`, `login_error`, `fetch_error`, `session_expired`
|
|
- **ImportZugferd**: Prüft auf hängende `ImportZugferdScheduled` Cronjobs
|
|
|
|
## Admin-Seite (`admin/setup.php`)
|
|
|
|
- Einstellung: Cron-Prüfintervall
|
|
- Aktion: Alle Benachrichtigungen löschen (löscht alle `GLOBALNOTIFY_*` Konstanten)
|
|
- Aktion: Hängende Cron-Jobs zurücksetzen (`processing=0`)
|
|
- Tabelle: Cron-Job Übersicht mit Status
|
|
- Tabelle: Alle Benachrichtigungen mit Typ, Modul, Datum, Gelesen-Status
|
|
|
|
## Wichtige Konventionen
|
|
|
|
- Duplikat-Erkennung: Vor dem Erstellen wird geprüft, ob eine gleichartige ungelesene Notification existiert
|
|
- Prioritäts-Sortierung: Höchste Priorität + neuestes Datum zuerst
|
|
- `user_id=0` bedeutet: sichtbar für alle Admins
|
|
- Dark Mode wird via `prefers-color-scheme: dark` CSS Media Query unterstützt
|
|
- Keine eigenen DB-Tabellen, alles über `llx_const`
|