Fix notifications and document setup
This commit is contained in:
@@ -172,7 +172,7 @@ class Waf extends Page implements HasForms, HasTable
|
||||
$entries = [];
|
||||
}
|
||||
|
||||
$this->auditEntries = $this->markWhitelisted($entries);
|
||||
$this->auditEntries = $this->normalizeAuditEntries($this->markWhitelisted($entries));
|
||||
$this->auditLoaded = true;
|
||||
|
||||
if ($notify) {
|
||||
@@ -254,6 +254,21 @@ class Waf extends Page implements HasForms, HasTable
|
||||
return $entries;
|
||||
}
|
||||
|
||||
protected function normalizeAuditEntries(array $entries): array
|
||||
{
|
||||
return array_map(function (array $entry): array {
|
||||
$entry['__key'] = md5(implode('|', [
|
||||
(string) ($entry['timestamp'] ?? ''),
|
||||
(string) ($entry['rule_id'] ?? ''),
|
||||
(string) ($entry['uri'] ?? ''),
|
||||
(string) ($entry['remote_ip'] ?? ''),
|
||||
(string) ($entry['host'] ?? ''),
|
||||
]));
|
||||
|
||||
return $entry;
|
||||
}, $entries);
|
||||
}
|
||||
|
||||
protected function matchesWhitelist(array $entry, array $rules): bool
|
||||
{
|
||||
$ruleId = (string) ($entry['rule_id'] ?? '');
|
||||
|
||||
@@ -15,6 +15,7 @@ use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Concerns\InteractsWithForms;
|
||||
use Filament\Forms\Contracts\HasForms;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Support\Contracts\TranslatableContentDriver;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Concerns\InteractsWithTable;
|
||||
use Filament\Tables\Contracts\HasTable;
|
||||
@@ -40,6 +41,11 @@ class WafWhitelistTable extends Component implements HasTable, HasForms, HasActi
|
||||
return view('livewire.admin.waf-whitelist-table');
|
||||
}
|
||||
|
||||
public function makeFilamentTranslatableContentDriver(): ?TranslatableContentDriver
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace App\Providers;
|
||||
|
||||
use App\Models\Domain;
|
||||
use App\Observers\DomainObserver;
|
||||
use Filament\Support\Facades\FilamentView;
|
||||
use Filament\View\PanelsRenderHook;
|
||||
use App\Support\Notifications\Notification as LivewireNotification;
|
||||
use Filament\Notifications\Notification;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
@@ -15,7 +15,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
$this->app->bind(Notification::class, LivewireNotification::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,10 +27,5 @@ class AppServiceProvider extends ServiceProvider
|
||||
|
||||
// Note: AuthEventListener is auto-discovered by Laravel 11+
|
||||
// Do not manually subscribe - it causes duplicate audit log entries
|
||||
|
||||
FilamentView::registerRenderHook(
|
||||
PanelsRenderHook::SCRIPTS_AFTER,
|
||||
fn (): string => view('filament.partials.notifications-refresh')->render(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
27
app/Support/Notifications/Notification.php
Normal file
27
app/Support/Notifications/Notification.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Support\Notifications;
|
||||
|
||||
use Filament\Notifications\Notification as BaseNotification;
|
||||
use Livewire\Livewire;
|
||||
|
||||
class Notification extends BaseNotification
|
||||
{
|
||||
public function send(): static
|
||||
{
|
||||
$payload = $this->toArray();
|
||||
|
||||
if (Livewire::isLivewireRequest()) {
|
||||
$component = Livewire::current();
|
||||
if ($component) {
|
||||
$component->dispatch('notificationSent', $payload);
|
||||
}
|
||||
}
|
||||
|
||||
session()->push('filament.notifications', $payload);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -36,3 +36,19 @@ After install, systemd services are enabled and started:
|
||||
- `jabali-agent`
|
||||
- `jabali-queue`
|
||||
- `jabali-health-monitor`
|
||||
|
||||
## Panel notifications (admin + user)
|
||||
|
||||
Jabali ships with a hardened Filament notifications setup that prevents Livewire
|
||||
success hooks from breaking after the first toast.
|
||||
|
||||
What is included:
|
||||
|
||||
- `public/js/filament/notifications/notifications.js` is patched to guard the
|
||||
animation callback (prevents `TypeError: e is not a function`).
|
||||
- `resources/views/vendor/filament-notifications/notifications.blade.php` adds
|
||||
a lightweight `wire:poll.2s` so toasts keep flowing even if a Livewire event
|
||||
is dropped.
|
||||
|
||||
If you update or rebuild assets, keep the guard in place and hard‑refresh the
|
||||
browser (Ctrl+Shift+R) after deployment.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,57 +0,0 @@
|
||||
<script data-navigate-once>
|
||||
(function () {
|
||||
let hookRegistered = false;
|
||||
|
||||
const registerHook = () => {
|
||||
if (hookRegistered || !window.Livewire?.hook || !window.Livewire?.dispatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
hookRegistered = true;
|
||||
|
||||
window.Livewire.hook('commit', ({ component, succeed }) => {
|
||||
if (component?.name === 'notifications') {
|
||||
return;
|
||||
}
|
||||
|
||||
succeed(() => {
|
||||
const livewire = window.Livewire;
|
||||
const allComponents = typeof livewire?.all === 'function' ? livewire.all() : [];
|
||||
const notificationsComponent = allComponents.find((component) => {
|
||||
const name = component?.name ?? '';
|
||||
return name === 'notifications' || name.includes('notifications');
|
||||
});
|
||||
|
||||
if (notificationsComponent?.$wire?.pullNotificationsFromSession) {
|
||||
try {
|
||||
notificationsComponent.$wire.pullNotificationsFromSession();
|
||||
return;
|
||||
} catch (error) {
|
||||
// fall back to dispatch-based refresh
|
||||
}
|
||||
}
|
||||
|
||||
const dispatchTo = livewire?.dispatchTo;
|
||||
if (dispatchTo) {
|
||||
['notifications', 'filament.notifications', 'filament-notifications'].forEach((name) => {
|
||||
try {
|
||||
dispatchTo(name, 'notificationsSent');
|
||||
} catch (error) {
|
||||
// ignore missing component names
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
livewire?.dispatch?.('notificationsSent');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
document.addEventListener('livewire:init', registerHook);
|
||||
document.addEventListener('livewire:navigated', registerHook);
|
||||
|
||||
if (window.Livewire?.hook) {
|
||||
registerHook();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
43
resources/views/vendor/filament-notifications/notifications.blade.php
vendored
Normal file
43
resources/views/vendor/filament-notifications/notifications.blade.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
@php
|
||||
use Filament\Support\Enums\Alignment;
|
||||
use Filament\Support\Enums\VerticalAlignment;
|
||||
@endphp
|
||||
|
||||
<div wire:poll.2s="pullNotificationsFromSession">
|
||||
<div
|
||||
@class([
|
||||
'fi-no',
|
||||
'fi-align-' . static::$alignment->value,
|
||||
'fi-vertical-align-' . static::$verticalAlignment->value,
|
||||
])
|
||||
role="status"
|
||||
>
|
||||
@foreach ($notifications as $notification)
|
||||
{{ $notification }}
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@if ($broadcastChannel = $this->getBroadcastChannel())
|
||||
@script
|
||||
<script>
|
||||
window.addEventListener('EchoLoaded', () => {
|
||||
window.Echo.private(@js($broadcastChannel)).notification(
|
||||
(notification) => {
|
||||
setTimeout(
|
||||
() =>
|
||||
$wire.handleBroadcastNotification(
|
||||
notification,
|
||||
),
|
||||
500,
|
||||
)
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
if (window.Echo) {
|
||||
window.dispatchEvent(new CustomEvent('EchoLoaded'))
|
||||
}
|
||||
</script>
|
||||
@endscript
|
||||
@endif
|
||||
</div>
|
||||
Reference in New Issue
Block a user