No description
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> |
||
|---|---|---|
| admin | ||
| ajax | ||
| class | ||
| core/modules | ||
| css | ||
| js | ||
| langs | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| README.md | ||
GlobalNotify - Dolibarr Benachrichtigungsmodul
Ein zentrales Benachrichtigungssystem für Dolibarr, das Meldungen von allen Modulen sammelt und in einem schwebenden Widget anzeigt.
Features
- Schwebendes Widget: Messenger-artiges Panel, immer sichtbar (unten links)
- Verschiebbar: FAB-Button kann frei positioniert werden (Position wird gespeichert)
- Benachrichtigungston: Akustisches Signal bei neuen Nachrichten
- Shake-Animation: Visuelle Aufmerksamkeit bei neuen Benachrichtigungen
- Farbkodierung:
- Grau: Keine Benachrichtigungen
- Rot: Benachrichtigungen vorhanden
- Pulsierend rot: Dringende Benachrichtigungen (Fehler/Aktionen)
- Historie: Gelesene Benachrichtigungen bleiben in der Historie verfügbar
- Cron-Überwachung: Automatische Erkennung hängender Cron-Jobs
Installation
- Modul nach
/custom/globalnotify/kopieren - In Dolibarr unter Einstellungen → Module → GlobalNotify aktivieren
- Konfiguration unter Einstellungen → Module → GlobalNotify → Setup
Einstellungen
- Cron-Prüfintervall: Wie oft auf hängende Cron-Jobs geprüft wird (10-3600 Sekunden)
Integration in andere Module
Grundprinzip
GlobalNotify bietet eine einfache API zum Erstellen von Benachrichtigungen. Wichtig: Module sollten immer prüfen, ob GlobalNotify verfügbar ist, bevor sie es verwenden.
Sichere Integration (empfohlen)
<?php
/**
* Sendet eine Benachrichtigung über GlobalNotify (falls verfügbar)
*
* @param string $type 'error', 'warning', 'info', 'success', 'action'
* @param string $title Kurzer Titel
* @param string $message Detaillierte Nachricht
* @param string $actionUrl URL für Aktions-Button (optional)
* @param string $actionLabel Label für Aktions-Button (optional)
* @return bool True wenn gesendet, false wenn GlobalNotify nicht verfügbar
*/
function mymodule_notify($type, $title, $message, $actionUrl = '', $actionLabel = '')
{
global $db;
// Prüfe ob GlobalNotify aktiv ist
if (!isModEnabled('globalnotify')) {
return false;
}
// Versuche die Klasse zu laden
$classFile = dol_buildpath('/globalnotify/class/globalnotify.class.php', 0);
if (!file_exists($classFile)) {
return false;
}
require_once $classFile;
if (!class_exists('GlobalNotify')) {
return false;
}
// Benachrichtigung senden
try {
switch ($type) {
case 'error':
GlobalNotify::error('mymodule', $title, $message, $actionUrl, $actionLabel);
break;
case 'warning':
GlobalNotify::warning('mymodule', $title, $message, $actionUrl, $actionLabel);
break;
case 'info':
GlobalNotify::info('mymodule', $title, $message, $actionUrl, $actionLabel);
break;
case 'action':
GlobalNotify::actionRequired('mymodule', $title, $message, $actionUrl, $actionLabel ?: 'Aktion erforderlich');
break;
default:
GlobalNotify::info('mymodule', $title, $message, $actionUrl, $actionLabel);
}
return true;
} catch (Exception $e) {
dol_syslog('GlobalNotify error: '.$e->getMessage(), LOG_WARNING);
return false;
}
}
Direkte Nutzung der Klasse
<?php
// GlobalNotify einbinden (mit Sicherheitsprüfung)
if (isModEnabled('globalnotify')) {
dol_include_once('/globalnotify/class/globalnotify.class.php');
}
// Irgendwo im Code...
if (class_exists('GlobalNotify')) {
$notify = new GlobalNotify($db);
// Fehler-Benachrichtigung (höchste Priorität 10)
$notify->addNotification(
'mymodule', // Modul-Name
GlobalNotify::TYPE_ERROR, // Typ
'Import fehlgeschlagen', // Titel
'Die Datei konnte nicht gelesen werden: file.pdf', // Nachricht
dol_buildpath('/mymodule/list.php', 1), // Aktions-URL
'Details anzeigen', // Aktions-Label
10, // Priorität (1-10)
0 // User-ID (0 = alle Admins)
);
}
Statische Helper-Methoden
<?php
// Nur wenn GlobalNotify verfügbar
if (class_exists('GlobalNotify')) {
// Fehler (Priorität 10)
GlobalNotify::error('mymodule', 'Titel', 'Nachricht', 'url', 'Button-Text');
// Warnung (Priorität 7)
GlobalNotify::warning('mymodule', 'Titel', 'Nachricht', 'url', 'Button-Text');
// Info (Priorität 3)
GlobalNotify::info('mymodule', 'Titel', 'Nachricht', 'url', 'Button-Text');
// Aktion erforderlich (Priorität 9)
GlobalNotify::actionRequired('mymodule', 'Titel', 'Nachricht', 'url', 'Button-Text');
}
Benachrichtigungstypen
| Typ | Konstante | Priorität | Verwendung |
|---|---|---|---|
| error | TYPE_ERROR |
10 | Kritische Fehler, System-Probleme |
| warning | TYPE_WARNING |
7 | Warnungen, potentielle Probleme |
| info | TYPE_INFO |
3 | Informationen, Status-Updates |
| success | TYPE_SUCCESS |
3 | Erfolgreiche Aktionen |
| action | TYPE_ACTION |
9 | Benutzer-Aktion erforderlich |
Beispiel: Cron-Job mit Fehlerbenachrichtigung
<?php
class MyCronJob
{
public function run()
{
try {
// ... Cron-Logik ...
if ($errorCount > 0) {
$this->notifyAdmin(
'warning',
'Import mit Warnungen',
"{$errorCount} Dateien konnten nicht importiert werden"
);
}
} catch (Exception $e) {
$this->notifyAdmin(
'error',
'Cron-Job fehlgeschlagen',
$e->getMessage(),
dol_buildpath('/mymodule/admin/setup.php', 1),
'Einstellungen prüfen'
);
return -1;
}
return 0;
}
private function notifyAdmin($type, $title, $message, $url = '', $label = '')
{
if (!isModEnabled('globalnotify')) {
// Fallback: Nur ins Log schreiben
dol_syslog("MyModule: {$title} - {$message}", LOG_WARNING);
return;
}
dol_include_once('/globalnotify/class/globalnotify.class.php');
if (class_exists('GlobalNotify')) {
switch ($type) {
case 'error':
GlobalNotify::error('mymodule', $title, $message, $url, $label);
break;
case 'warning':
GlobalNotify::warning('mymodule', $title, $message, $url, $label);
break;
default:
GlobalNotify::info('mymodule', $title, $message, $url, $label);
}
}
}
}
Benachrichtigungen verwalten
<?php
dol_include_once('/globalnotify/class/globalnotify.class.php');
$notify = new GlobalNotify($db);
// Alle ungelesenen Benachrichtigungen holen
$unread = $notify->getAllNotifications($user->id, true);
// Gelesene Benachrichtigungen (Historie)
$history = $notify->getReadNotifications($user->id, 20);
// Als gelesen markieren
$notify->markAsRead($notificationId);
// Alle als gelesen markieren
$notify->markAllAsRead();
// Nur für ein bestimmtes Modul
$notify->markAllAsRead('mymodule');
// Benachrichtigung löschen
$notify->deleteNotification($notificationId);
// Alle Benachrichtigungen eines Moduls löschen
$notify->clearModuleNotifications('mymodule');
// Ungelesene Anzahl für Badge
$count = $notify->getUnreadCount();
Best Practices
1. Immer Verfügbarkeit prüfen
// RICHTIG
if (isModEnabled('globalnotify') && class_exists('GlobalNotify')) {
GlobalNotify::error('mymodule', 'Fehler', 'Details');
}
// FALSCH - kann zu Fatal Error führen
GlobalNotify::error('mymodule', 'Fehler', 'Details');
2. Nicht zu viele Benachrichtigungen
GlobalNotify speichert maximal 50 Benachrichtigungen pro Modul. Vermeiden Sie:
- Benachrichtigungen in Schleifen
- Benachrichtigungen für jeden einzelnen Datensatz
- Wiederholte identische Benachrichtigungen
3. Aussagekräftige Informationen
// RICHTIG
GlobalNotify::error(
'bankimport',
'Bank-Login fehlgeschlagen',
'Sparkasse Musterstadt: Falsches Passwort (3. Versuch)',
dol_buildpath('/bankimport/admin/setup.php', 1),
'Zugangsdaten prüfen'
);
// FALSCH
GlobalNotify::error('bankimport', 'Fehler', 'Es ist ein Fehler aufgetreten');
4. Sinnvolle Aktions-URLs
Wenn eine Benachrichtigung eine Aktion erfordert, fügen Sie immer eine URL hinzu:
GlobalNotify::actionRequired(
'importzugferd',
'Lieferant nicht gefunden',
'Rechnung von "Neue Firma GmbH" konnte nicht zugeordnet werden',
dol_buildpath('/importzugferd/pending.php?id=123', 1),
'Rechnung prüfen'
);
Technische Details
Speicherung
Benachrichtigungen werden in llx_const als JSON gespeichert:
- Key:
GLOBALNOTIFY_<MODULNAME>(z.B.GLOBALNOTIFY_BANKIMPORT) - Value: JSON-Array mit Benachrichtigungen
Caching
- Cron-Prüfung: Konfigurierbar (Standard: 60 Sekunden)
- Client-Refresh: Alle 2 Minuten via AJAX
Hooks
Das Modul nutzt folgende Hooks:
printTopRightMenu- Widget-AnzeigeaddMoreActionsButtons- Modul-Status-Checks
Changelog
Siehe CHANGELOG.md
Lizenz
GPL v3 - siehe LICENSE
Autor
Eduard Wisch - Data IT Solution https://data-it-solution.de