Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion resources/views/components/notification.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class="m-auto d-flex align-items-center btn btn-link position-relative px-1 py-0 h-100 link-body-emphasis"
data-controller="notification"
data-action="click->notification#fetch"
data-notification-count-value="{{ count($notifications) }}"
data-notification-count-value="{{ $unreadCount }}"
data-notification-url-value="{{ route('orchid.notifications.unreadCount') }}"
data-notification-method-value="post"
data-notification-interval-value="{{ config('orchid.notifications.interval') }}"
Expand Down
12 changes: 8 additions & 4 deletions src/Platform/Components/Notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

class Notification extends Component
{
private const COUNT_INDICATOR_THRESHOLD = 10;

/**
* @var Authenticatable|null
*/
Expand All @@ -33,14 +35,16 @@ public function __construct(Guard $guard)
*/
public function render()
{
$notifications = $this->user
$unreadCount = $this->user
->unreadNotifications()
->whereIn('type', [OrchidMessage::class, DashboardMessage::class])
->limit(15)
->get();
->reorder()
->limit(self::COUNT_INDICATOR_THRESHOLD)
->pluck('id')
->count();

return view('orchid::components.notification', [
'notifications' => $notifications,
'unreadCount' => $unreadCount,
]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Platform/Http/Controllers/NotificationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function markAllAsRead(Request $request): RedirectResponse
public function unreadCount(Request $request): array
{
$total = $request->user()
->unreadNotifications
->unreadNotifications()
->whereIn('type', [OrchidMessage::class, DashboardMessage::class])
->count();

Expand Down
1 change: 1 addition & 0 deletions stubs/app/Orchid/Screens/Examples/ExampleScreen.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public function layout(): iterable
->render(fn (Repository $model) => // Please use view('path')
"<img src='https://loremflickr.com/500/300?random={$model->get('id')}'
alt='sample'
loading='lazy'
class='mw-100 d-block img-fluid rounded-1 w-100'>
<span class='small text-muted mt-1 mb-0'># {$model->get('id')}</span>"),

Expand Down
43 changes: 43 additions & 0 deletions tests/Browser/NotificationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Orchid\Tests\Browser;

use Laravel\Dusk\Browser;
use Orchid\Tests\Database\Factory\DatabaseNotificationFactory;
use Orchid\Tests\TestBrowserCase;

class NotificationTest extends TestBrowserCase
{
public function testNotificationBadgeSwitchesToIndicatorForDoubleDigitCounts(): void
{
$user = $this->createAdminUser();

DatabaseNotificationFactory::new()
->count(9)
->for($user, 'notifiable')
->create();

$this->browse(function (Browser $browser) use ($user) {
$badge = '[data-notification-target="badge"]';

$browser
->loginAs($user)
->visitRoute(config('orchid.index'))
->waitFor("{$badge}:not(.d-none)")
->assertSeeIn($badge, '9')
->assertMissing("{$badge} svg");

DatabaseNotificationFactory::new()
->count(2)
->for($user, 'notifiable')
->create();

$browser
->refresh()
->waitFor("{$badge} svg")
->assertDontSeeIn($badge, '10');
});
}
}
25 changes: 25 additions & 0 deletions tests/Database/Factory/DatabaseNotificationFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Orchid\Tests\Database\Factory;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Support\Str;
use Orchid\Platform\Notifications\OrchidMessage;

class DatabaseNotificationFactory extends Factory
{
protected $model = DatabaseNotification::class;

public function definition(): array
{
return [
'id' => (string) Str::uuid(),
'type' => OrchidMessage::class,
'data' => [],
'read_at' => null,
];
}
}
28 changes: 28 additions & 0 deletions tests/Feature/Platform/NotificationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

namespace Orchid\Tests\Feature\Platform;

use Illuminate\Notifications\DatabaseNotification;
use Orchid\Platform\Components\Notification;
use Orchid\Platform\Models\User;
use Orchid\Platform\Notifications\OrchidMessage;
use Orchid\Support\Color;
use Orchid\Tests\App\Notifications\TaskCompleted;
use Orchid\Tests\Database\Factory\DatabaseNotificationFactory;
use Orchid\Tests\TestFeatureCase;

class NotificationTest extends TestFeatureCase
Expand Down Expand Up @@ -86,6 +89,31 @@ public function testUnreadCount(): void
$response
->assertOk()
->assertJson(['total' => 1]);

$this->assertFalse(
$user->relationLoaded('unreadNotifications'),
'Counting unread notifications must not hydrate the notification relation.',
);
}

public function testNotificationBadgeCapsDoubleDigitCountForFrontendIndicator(): void
{
$user = $this->createAdminUser();

DatabaseNotificationFactory::new()
->count(11)
->for($user, 'notifiable')
->create();

$this->actingAs($user);

DatabaseNotification::retrieved(
fn () => $this->fail('Rendering the notification badge must not hydrate notification models.')
);

$view = $this->app->make(Notification::class)->render();

$this->assertSame(10, $view->getData()['unreadCount']);
}

private function createNotifyUser(): User
Expand Down
Loading