diff --git a/packages/app/resources/views/components/layouts/app/topbar/index.blade.php b/packages/app/resources/views/components/layouts/app/topbar/index.blade.php
index 63ce7a53fc..cece985eba 100644
--- a/packages/app/resources/views/components/layouts/app/topbar/index.blade.php
+++ b/packages/app/resources/views/components/layouts/app/topbar/index.blade.php
@@ -87,7 +87,9 @@
@livewire('filament.core.global-search')
- @livewire('filament.core.notifications')
+ @if (filament()->hasDatabaseNotifications())
+ @livewire('filament.core.database-notifications')
+ @endif
diff --git a/packages/app/resources/views/components/layouts/base.blade.php b/packages/app/resources/views/components/layouts/base.blade.php
index 31cc78289c..be4c7532f0 100644
--- a/packages/app/resources/views/components/layouts/base.blade.php
+++ b/packages/app/resources/views/components/layouts/base.blade.php
@@ -86,6 +86,8 @@
{{ $slot }}
+ @livewire('filament.core.notifications')
+
{{ filament()->renderHook('scripts.start') }}
@livewireScripts
diff --git a/packages/app/resources/views/components/layouts/card.blade.php b/packages/app/resources/views/components/layouts/card.blade.php
index 17ddf87026..37878ff5c0 100644
--- a/packages/app/resources/views/components/layouts/card.blade.php
+++ b/packages/app/resources/views/components/layouts/card.blade.php
@@ -54,14 +54,10 @@
@if (filament()->auth()->check())
- @livewire('filament.core.notifications')
+ @livewire('filament.core.database-notifications')
@endif
-
- @if (! filament()->auth()->check())
- @livewire('filament.core.notifications')
- @endif
diff --git a/packages/app/src/Context/Concerns/HasComponents.php b/packages/app/src/Context/Concerns/HasComponents.php
index aa3facdd01..f5163a48ba 100644
--- a/packages/app/src/Context/Concerns/HasComponents.php
+++ b/packages/app/src/Context/Concerns/HasComponents.php
@@ -2,6 +2,7 @@
namespace Filament\Context\Concerns;
+use Filament\Http\Livewire\DatabaseNotifications;
use Filament\Http\Livewire\GlobalSearch;
use Filament\Http\Livewire\Notifications;
use Filament\Pages\Page;
@@ -262,6 +263,7 @@ trait HasComponents
public function registerLivewireComponents(): void
{
+ $this->queueLivewireComponentForRegistration(DatabaseNotifications::class);
$this->queueLivewireComponentForRegistration(GlobalSearch::class);
$this->queueLivewireComponentForRegistration(Notifications::class);
diff --git a/packages/app/src/Http/Livewire/DatabaseNotifications.php b/packages/app/src/Http/Livewire/DatabaseNotifications.php
new file mode 100644
index 0000000000..8bf12e6271
--- /dev/null
+++ b/packages/app/src/Http/Livewire/DatabaseNotifications.php
@@ -0,0 +1,32 @@
+user();
+ }
+
+ public function getPollingInterval(): ?string
+ {
+ return Filament::getDatabaseNotificationsPollingInterval();
+ }
+
+ public function getTrigger(): View
+ {
+ return view('filament::components.layouts.app.topbar.database-notifications-trigger');
+ }
+
+ public static function getName(): string
+ {
+ return 'filament.core.database-notifications';
+ }
+}
diff --git a/packages/app/src/Http/Livewire/Notifications.php b/packages/app/src/Http/Livewire/Notifications.php
index 9d8933138c..ba564ca3cb 100644
--- a/packages/app/src/Http/Livewire/Notifications.php
+++ b/packages/app/src/Http/Livewire/Notifications.php
@@ -5,7 +5,6 @@ namespace Filament\Http\Livewire;
use Filament\Facades\Filament;
use Filament\Notifications\Http\Livewire\Notifications as BaseComponent;
use Illuminate\Contracts\Auth\Authenticatable;
-use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\Model;
class Notifications extends BaseComponent
@@ -15,21 +14,6 @@ class Notifications extends BaseComponent
return Filament::auth()->user();
}
- public function hasDatabaseNotifications(): bool
- {
- return $this->getUser() && Filament::hasDatabaseNotifications();
- }
-
- public function getPollingInterval(): ?string
- {
- return Filament::getDatabaseNotificationsPollingInterval();
- }
-
- public function getDatabaseNotificationsTrigger(): View
- {
- return view('filament::components.layouts.app.topbar.database-notifications-trigger');
- }
-
public static function getName(): string
{
return 'filament.core.notifications';
diff --git a/packages/notifications/docs/03-database-notifications.md b/packages/notifications/docs/03-database-notifications.md
index 03b879bfd9..102cc9145f 100644
--- a/packages/notifications/docs/03-database-notifications.md
+++ b/packages/notifications/docs/03-database-notifications.md
@@ -4,8 +4,6 @@ title: Database notifications
## Overview
-> To start, make sure the package is [installed](installation) - `@livewire('notifications')` should be in your Blade layout somewhere.
-
Before we start, make sure that the [Laravel notifications table](https://laravel.com/docs/notifications#database-prerequisites) is added to your database:
```bash
@@ -16,12 +14,10 @@ php artisan notifications:table
> If you're using UUIDs for your `User` model, make sure that your `notifiable` column is using `uuidMorphs()`: `$table->uuidMorphs('notifiable')`.
-To enable database notifications, add the following to a service provider:
+To add database notifications to your app, you must add a new Livewire component to your Blade layout:
-```php
-use Filament\Notifications\Http\Livewire\Notifications;
-
-Notifications::databaseNotifications();
+```blade
+@livewire('database-notifications')
```
Database notifications will be rendered within a modal. To open this modal, you must have a "trigger" button in your view. Create a new trigger button component in your app, for instance at `/resources/views/notifications/database-notifications-trigger.blade.php`:
@@ -37,13 +33,12 @@ Database notifications will be rendered within a modal. To open this modal, you
In the service provider, point to this new trigger view:
```php
-use Filament\Notifications\Http\Livewire\Notifications;
+use Filament\Notifications\Http\Livewire\DatabaseNotifications;
-Notifications::databaseNotifications();
-Notifications::databaseNotificationsTrigger('filament-notifications.database-notifications-trigger');
+DatabaseNotifications::trigger('filament-notifications.database-notifications-trigger');
```
-Now, simply move the `@livewire('notifications')` component to the position in your HTML that you wish to render the database notifications trigger button. It should appear, and open the database notifications modal when clicked!
+Now, click on the trigger button that is rendered in your view. A modal should appear containing your database notifications when clicked!
## Sending database notifications
@@ -100,19 +95,19 @@ Polling is the practice of periodically making a request to the server to check
By default, Livewire polls for new notifications every 30 seconds:
```php
-use Filament\Notifications\Http\Livewire\Notifications;
+use Filament\Notifications\Http\Livewire\DatabaseNotifications;
-Notifications::databaseNotifications();
-Notifications::databaseNotificationsPollingInterval('30s');
+DatabaseNotifications::databaseNotifications();
+DatabaseNotifications::databaseNotificationsPollingInterval('30s');
```
You may completely disable polling if you wish:
```php
-use Filament\Notifications\Http\Livewire\Notifications;
+use Filament\Notifications\Http\Livewire\DatabaseNotifications;
-Notifications::databaseNotifications();
-Notifications::databaseNotificationsPollingInterval(null);
+DatabaseNotifications::databaseNotifications();
+DatabaseNotifications::databaseNotificationsPollingInterval(null);
```
### Using Echo to receive new database notifications with websockets
diff --git a/packages/notifications/resources/js/components/notification.js b/packages/notifications/resources/js/components/notification.js
index ad6daafc37..c6cb4dcf8e 100644
--- a/packages/notifications/resources/js/components/notification.js
+++ b/packages/notifications/resources/js/components/notification.js
@@ -107,7 +107,7 @@ export default (Alpine) => {
this.isShown = false
setTimeout(
- () => Livewire.emit('notificationClosed', notification.id),
+ () => Livewire.emitUp('notificationClosed', notification.id),
this.getTransitionDuration(),
)
},
diff --git a/packages/notifications/resources/views/components/database/echo.blade.php b/packages/notifications/resources/views/components/database/echo.blade.php
new file mode 100644
index 0000000000..1d5acd5790
--- /dev/null
+++ b/packages/notifications/resources/views/components/database/echo.blade.php
@@ -0,0 +1,16 @@
+@props([
+ 'channel',
+])
+
+
diff --git a/packages/notifications/resources/views/components/database/modal/actions.blade.php b/packages/notifications/resources/views/components/database/modal/actions.blade.php
index 4d9521afe8..b7daede301 100644
--- a/packages/notifications/resources/views/components/database/modal/actions.blade.php
+++ b/packages/notifications/resources/views/components/database/modal/actions.blade.php
@@ -8,11 +8,11 @@
@if ($unreadNotificationsCount)
@@ -25,12 +25,12 @@
@endif
diff --git a/packages/notifications/resources/views/components/database/modal/index.blade.php b/packages/notifications/resources/views/components/database/modal/index.blade.php
index a90a78e89c..6a71f8964e 100644
--- a/packages/notifications/resources/views/components/database/modal/index.blade.php
+++ b/packages/notifications/resources/views/components/database/modal/index.blade.php
@@ -32,7 +32,7 @@
'py-2 ps-4 pe-2',
'bg-primary-50 -mb-px dark:bg-gray-700' => $notification->unread(),
])>
- {{ $this->getNotificationFromDatabaseRecord($notification)->inline() }}
+ {{ $this->getNotification($notification)->inline() }}
@endforeach
diff --git a/packages/notifications/resources/views/components/echo.blade.php b/packages/notifications/resources/views/components/echo.blade.php
index 851dfb17cf..757757fe85 100644
--- a/packages/notifications/resources/views/components/echo.blade.php
+++ b/packages/notifications/resources/views/components/echo.blade.php
@@ -10,9 +10,6 @@
.notification((notification) => {
setTimeout(() => $wire.handleBroadcastNotification(notification), 500)
})
- .listen('.database-notifications.sent', () => {
- setTimeout(() => $wire.call('$refresh'), 500)
- })
})
if (window.Echo) {
diff --git a/packages/notifications/resources/views/components/database/index.blade.php b/packages/notifications/resources/views/database-notifications.blade.php
similarity index 52%
rename from packages/notifications/resources/views/components/database/index.blade.php
rename to packages/notifications/resources/views/database-notifications.blade.php
index eb739f55b7..e55832c68f 100644
--- a/packages/notifications/resources/views/components/database/index.blade.php
+++ b/packages/notifications/resources/views/database-notifications.blade.php
@@ -1,6 +1,6 @@
@php
- $notifications = $this->getDatabaseNotifications();
- $unreadNotificationsCount = $this->getUnreadDatabaseNotificationsCount();
+ $notifications = $this->getNotifications();
+ $unreadNotificationsCount = $this->getUnreadNotificationsCount();
@endphp
- @if ($databaseNotificationsTrigger = $this->getDatabaseNotificationsTrigger())
+ @if ($trigger = $this->getTrigger())
- {{ $databaseNotificationsTrigger->with(['unreadNotificationsCount' => $unreadNotificationsCount]) }}
+ {{ $trigger->with(['unreadNotificationsCount' => $unreadNotificationsCount]) }}
@endif
@@ -19,4 +19,8 @@
:notifications="$notifications"
:unread-notifications-count="$unreadNotificationsCount"
/>
+
+ @if ($broadcastChannel = $this->getBroadcastChannel())
+
+ @endif
diff --git a/packages/notifications/resources/views/notification.blade.php b/packages/notifications/resources/views/notification.blade.php
index 0c9586c260..64e39484e2 100644
--- a/packages/notifications/resources/views/notification.blade.php
+++ b/packages/notifications/resources/views/notification.blade.php
@@ -1,3 +1,4 @@
+@php use Filament\Notifications\Http\Livewire\Notifications; @endphp
diff --git a/packages/notifications/resources/views/notifications.blade.php b/packages/notifications/resources/views/notifications.blade.php
index 009d99c93e..f921a55b99 100644
--- a/packages/notifications/resources/views/notifications.blade.php
+++ b/packages/notifications/resources/views/notifications.blade.php
@@ -20,10 +20,6 @@
@endforeach
- @if ($this->hasDatabaseNotifications())
-
- @endif
-
@if ($broadcastChannel = $this->getBroadcastChannel())
@endif
diff --git a/packages/notifications/src/Http/Livewire/DatabaseNotifications.php b/packages/notifications/src/Http/Livewire/DatabaseNotifications.php
new file mode 100644
index 0000000000..1def75af3a
--- /dev/null
+++ b/packages/notifications/src/Http/Livewire/DatabaseNotifications.php
@@ -0,0 +1,134 @@
+
+ */
+ protected $listeners = [
+ 'notificationClosed' => 'removeNotification',
+ ];
+
+ public static ?string $trigger = null;
+
+ public static ?string $pollingInterval = '30s';
+
+ public function removeNotification(string $id): void
+ {
+ $this->getNotificationsQuery()
+ ->where('id', $id)
+ ->delete();
+ }
+
+ public function clearNotifications(): void
+ {
+ $this->getNotificationsQuery()->delete();
+ }
+
+ public function markAllNotificationsAsRead(): void
+ {
+ $this->getUnreadNotificationsQuery()->update(['read_at' => now()]);
+ }
+
+ public function getNotifications(): DatabaseNotificationCollection
+ {
+ /** @phpstan-ignore-next-line */
+ return $this->getNotificationsQuery()->get();
+ }
+
+ public function getNotificationsQuery(): Builder | Relation
+ {
+ /** @phpstan-ignore-next-line */
+ return $this->getUser()->notifications()->where('data->format', 'filament');
+ }
+
+ public function getUnreadNotificationsQuery(): Builder | Relation
+ {
+ /** @phpstan-ignore-next-line */
+ return $this->getNotificationsQuery()->unread();
+ }
+
+ public function getUnreadNotificationsCount(): int
+ {
+ return $this->getUnreadNotificationsQuery()->count();
+ }
+
+ public function getPollingInterval(): ?string
+ {
+ return static::$pollingInterval;
+ }
+
+ public function getTrigger(): ?View
+ {
+ $viewPath = static::$trigger;
+
+ if (blank($viewPath)) {
+ return null;
+ }
+
+ return view($viewPath);
+ }
+
+ public function getUser(): Model | Authenticatable | null
+ {
+ return auth()->user();
+ }
+
+ public function getBroadcastChannel(): ?string
+ {
+ $user = $this->getUser();
+
+ if (! $user) {
+ return null;
+ }
+
+ if (method_exists($user, 'receivesBroadcastNotificationsOn')) {
+ return $user->receivesBroadcastNotificationsOn();
+ }
+
+ $userClass = str_replace('\\', '.', $user::class);
+
+ return "{$userClass}.{$user->getKey()}";
+ }
+
+ public function getNotification(DatabaseNotification $notification): Notification
+ {
+ return Notification::fromDatabase($notification)
+ ->date($this->formatNotificationDate($notification->getAttributeValue('created_at')));
+ }
+
+ protected function formatNotificationDate(CarbonInterface $date): string
+ {
+ return $date->diffForHumans();
+ }
+
+ public static function trigger(?string $trigger): void
+ {
+ static::$trigger = $trigger;
+ }
+
+ public static function pollingInterval(?string $interval): void
+ {
+ static::$pollingInterval = $interval;
+ }
+
+ public function render(): View
+ {
+ return view('filament-notifications::database-notifications');
+ }
+}
diff --git a/packages/notifications/src/Http/Livewire/Notifications.php b/packages/notifications/src/Http/Livewire/Notifications.php
index 3948b7d67d..70483c2eb0 100644
--- a/packages/notifications/src/Http/Livewire/Notifications.php
+++ b/packages/notifications/src/Http/Livewire/Notifications.php
@@ -30,12 +30,6 @@ class Notifications extends Component
'notificationClosed' => 'removeNotification',
];
- public static bool $hasDatabaseNotifications = false;
-
- public static ?string $databaseNotificationsTrigger = null;
-
- public static ?string $databaseNotificationsPollingInterval = '30s';
-
public static string $horizontalAlignment = 'right';
public static string $verticalAlignment = 'top';
@@ -67,50 +61,11 @@ class Notifications extends Component
public function removeNotification(string $id): void
{
- if ($this->notifications->has($id)) {
- $this->notifications->forget($id);
- }
-
- if (! $this->hasDatabaseNotifications()) {
+ if (! $this->notifications->has($id)) {
return;
}
- $this->getDatabaseNotificationsQuery()
- ->where('id', $id)
- ->delete();
- }
-
- public function clearDatabaseNotifications(): void
- {
- $this->getDatabaseNotificationsQuery()->delete();
- }
-
- public function markAllDatabaseNotificationsAsRead(): void
- {
- $this->getUnreadDatabaseNotificationsQuery()->update(['read_at' => now()]);
- }
-
- public function getDatabaseNotifications(): DatabaseNotificationCollection
- {
- /** @phpstan-ignore-next-line */
- return $this->getDatabaseNotificationsQuery()->get();
- }
-
- public function getDatabaseNotificationsQuery(): Builder | Relation
- {
- /** @phpstan-ignore-next-line */
- return $this->getUser()->notifications()->where('data->format', 'filament');
- }
-
- public function getUnreadDatabaseNotificationsQuery(): Builder | Relation
- {
- /** @phpstan-ignore-next-line */
- return $this->getDatabaseNotificationsQuery()->unread();
- }
-
- public function getUnreadDatabaseNotificationsCount(): int
- {
- return $this->getUnreadDatabaseNotificationsQuery()->count();
+ $this->notifications->forget($id);
}
/**
@@ -133,27 +88,6 @@ class Notifications extends Component
);
}
- public function hasDatabaseNotifications(): bool
- {
- return $this->getUser() && static::$hasDatabaseNotifications;
- }
-
- public function getPollingInterval(): ?string
- {
- return static::$databaseNotificationsPollingInterval;
- }
-
- public function getDatabaseNotificationsTrigger(): ?View
- {
- $viewPath = static::$databaseNotificationsTrigger;
-
- if (blank($viewPath)) {
- return null;
- }
-
- return view($viewPath);
- }
-
public function getUser(): Model | Authenticatable | null
{
return auth()->user();
@@ -176,32 +110,6 @@ class Notifications extends Component
return "{$userClass}.{$user->getKey()}";
}
- public function getNotificationFromDatabaseRecord(DatabaseNotification $notification): Notification
- {
- return Notification::fromDatabase($notification)
- ->date($this->formatNotificationDate($notification->getAttributeValue('created_at')));
- }
-
- protected function formatNotificationDate(CarbonInterface $date): string
- {
- return $date->diffForHumans();
- }
-
- public static function databaseNotifications(bool $condition = true): void
- {
- static::$hasDatabaseNotifications = $condition;
- }
-
- public static function databaseNotificationsTrigger(?string $trigger): void
- {
- static::$databaseNotificationsTrigger = $trigger;
- }
-
- public static function databaseNotificationsPollingInterval(?string $interval): void
- {
- static::$databaseNotificationsPollingInterval = $interval;
- }
-
public static function horizontalAlignment(string $alignment): void
{
static::$horizontalAlignment = $alignment;
diff --git a/packages/notifications/src/NotificationsServiceProvider.php b/packages/notifications/src/NotificationsServiceProvider.php
index 06733d4ce6..43d1bd6659 100644
--- a/packages/notifications/src/NotificationsServiceProvider.php
+++ b/packages/notifications/src/NotificationsServiceProvider.php
@@ -2,6 +2,7 @@
namespace Filament\Notifications;
+use Filament\Notifications\Http\Livewire\DatabaseNotifications;
use Filament\Notifications\Http\Livewire\Notifications;
use Filament\Notifications\Testing\TestsNotifications;
use Filament\Support\Assets\AssetManager;
@@ -35,6 +36,8 @@ class NotificationsServiceProvider extends PackageServiceProvider
public function packageBooted(): void
{
+ Livewire::component('database-notifications', DatabaseNotifications::class);
+
Livewire::component('notifications', Notifications::class);
Livewire::listen('component.dehydrate', function (Component $component, Response $response): Response {