Powiadomienia (w aplikacji i mailowe)
View on GitHubPowiadomienia (w aplikacji i mailowe)
Orbit informuje użytkowników o aktywności na dwa sposoby: powiadomieniem w aplikacji (dropdown z dzwonkiem) oraz mailem, w podziale na App\Enums\Notifications\NotificationType — per użytkownik, per kanał, niezależnie przełączalne w ustawieniach konta. Ta kategoria dokumentuje ten system: jak event domenowy staje się powiadomieniem, jak preferencje per-użytkownik bramkują dostarczanie, oraz jeden krok, o którym łatwo zapomnieć przy dodawaniu nowego rodzaju powiadomienia.
Przewodniki, w kolejności, w jakiej faktycznie będą potrzebne
- Dodaj nowy typ powiadomienia
— przećwiczony przykład dodania
MemberRoleChanged(powiadamianie członka, gdy zmieni się jego rola w projekcie) od początku do końca: przypadek enuma, wystrzelenie i obsłużenie eventu oraz — krok, o którym łatwo zapomnieć — wiersz w ustawieniach na froncie, który w ogóle sprawia, że nowy typ jest widoczny i przełączalny. - Wyślij powiadomienie z własnego kodu
— pełny kontrakt
NotificationService::notify()(odbiorca, typ, ważność wizualna, wiadomość, URL akcji, co dokładnie robi każdy kanał), na wypadek gdy chcesz wysłać istniejący typ powiadomienia bezpośrednio, bez wprowadzania nowego eventu domenowego. - Przegląd połączenia frontend ↔ backend — jak powiadomienie faktycznie dociera do przeglądarki (to współdzielony prop Inertii, nie fetch), jak przebiega mark-as-read/mark-all-as-read/usuwanie oraz jak zakładka ustawień zapisuje przełącznik — przydatne jako mapa przed zagłębieniem się w którykolwiek z powyższych przewodników.
- Dodaj dedykowany mail transakcyjny
— przećwiczony przykład (
OwnershipTransferredMail) dla innego kształtu maila: takiego, który musi zostać wysłany bezwarunkowo, z własnym tematem i layoutem, całkowicie z pominięciemNotificationType/NotificationSetting— ten sam wzorzec, którego już używaProjectInvitationMail.
Podłączenie eventu domenowego do pipeline'u powiadomień jest samo w sobie udokumentowane w ramach
../integrations/03-add-a-new-event-type.md
(na przykładzie IssueCreated) — przewodnik 1 nie powtarza tego mechanizmu, tylko pokrywa wszystko, co jest specyficzne dla typów powiadomień ponad nim: wiersz w ustawieniach, domyślne wartości kanałów oraz podział frontend/backend, którego tamten przewodnik nie dotyka.
Architektura w jednym akapicie
Każdy fakt wart powiadomienia to jeden przypadek NotificationType (np. IssueAssigned, ProjectInvited). Każde powiadomienie może pójść jednym lub obydwoma z dwóch NotificationChannel — InApp (domyślnie włączony) i Email (domyślnie wyłączony, zobacz NotificationChannel::enabledByDefault()) — a użytkownik może nadpisać dowolny kanał dla dowolnego typu poprzez wiersz NotificationSetting (user_id + type + channel + enabled; brak wiersza oznacza "użyj domyślnej wartości kanału"). NotificationService::notify() to jedyny lejek, przez który wszystko przechodzi: zawsze prosi NotificationMailService o (ewentualne) wysłanie maila, a następnie sprawdza preferencję odbiorcy dla powiadomień w aplikacji, zanim w ogóle zapisze wiersz Notification — pominięcie tego sprawdzenia zapisywałoby wiersze dla kanałów, które użytkownik jawnie wyłączył. Eventy domenowe nie wywołują notify() bezpośrednio; SendNotificationListener::handle() to jedyne miejsce, które zamienia fakt "to się wydarzyło" (IssueAssigned, CommentAdded, ProjectInvited, …) w "powiadom tę konkretną osobę, z tym tytułem/wiadomością" — zobacz
../integrations/03-add-a-new-event-type.md
po to, jak sam event jest tworzony i rejestrowany. Na froncie tablica defaultNotificationTypes w AccountSettingsNotificationsTab.tsx to ręcznie utrzymywane lustro przypadków NotificationType z backendu (ikona, tytuł, opis per typ) — nic nie generuje jej z enuma, więc nowy typ z backendu jest niewidoczny w Ustawieniach, dopóki nie dodasz tam też jego wiersza.
