diff --git a/app/Notifications/NewPluginAvailable.php b/app/Notifications/NewPluginAvailable.php index 421ed730..a87c4809 100644 --- a/app/Notifications/NewPluginAvailable.php +++ b/app/Notifications/NewPluginAvailable.php @@ -34,7 +34,7 @@ public function toMail(object $notifiable): MailMessage ->subject("New Plugin: {$this->plugin->name}") ->greeting('A new plugin is available!') ->line("**{$this->plugin->name}** has just been added to the NativePHP Plugin Marketplace.") - ->action('View Plugin', url('/plugins')) + ->action('View Plugin', route('plugins.show', $this->plugin->routeParams())) ->line('You can manage your notification preferences in your account settings.'); } @@ -48,6 +48,8 @@ public function toArray(object $notifiable): array 'body' => "{$this->plugin->name} has just been added to the NativePHP Plugin Marketplace.", 'plugin_id' => $this->plugin->id, 'plugin_name' => $this->plugin->name, + 'action_url' => route('plugins.show', $this->plugin->routeParams()), + 'action_label' => 'View Plugin', ]; } } diff --git a/app/Notifications/PluginApproved.php b/app/Notifications/PluginApproved.php index 3161602b..75dd33a2 100644 --- a/app/Notifications/PluginApproved.php +++ b/app/Notifications/PluginApproved.php @@ -35,7 +35,7 @@ public function toMail(object $notifiable): MailMessage ->subject('Your Plugin Has Been Approved!') ->greeting('Great news!') ->line("Your plugin **{$this->plugin->name}** has been approved and is now listed in the NativePHP Plugin Marketplace.") - ->action('View Plugin Marketplace', url('/plugins')) + ->action('View Plugin', route('plugins.show', $this->plugin->routeParams())) ->line('Thank you for contributing to the NativePHP ecosystem!'); } @@ -51,6 +51,8 @@ public function toArray(object $notifiable): array 'body' => "{$this->plugin->name} is now listed in the NativePHP Plugin Marketplace.", 'plugin_id' => $this->plugin->id, 'plugin_name' => $this->plugin->name, + 'action_url' => route('plugins.show', $this->plugin->routeParams()), + 'action_label' => 'View Plugin', ]; } } diff --git a/app/Notifications/PluginRejected.php b/app/Notifications/PluginRejected.php index e743d894..230fbda7 100644 --- a/app/Notifications/PluginRejected.php +++ b/app/Notifications/PluginRejected.php @@ -37,7 +37,7 @@ public function toMail(object $notifiable): MailMessage ->line("Unfortunately, your plugin **{$this->plugin->name}** was not approved for the NativePHP Plugin Marketplace.") ->line('**Reason:**') ->line($this->plugin->rejection_reason) - ->action('View Your Plugins', route('customer.plugins.index')) + ->action('View Plugin', route('customer.plugins.show', $this->plugin->routeParams())) ->line('If you have questions about this decision, please reach out to us.'); } @@ -54,6 +54,8 @@ public function toArray(object $notifiable): array 'plugin_id' => $this->plugin->id, 'plugin_name' => $this->plugin->name, 'rejection_reason' => $this->plugin->rejection_reason, + 'action_url' => route('customer.plugins.show', $this->plugin->routeParams()), + 'action_label' => 'View Plugin', ]; } } diff --git a/resources/views/livewire/customer/notifications.blade.php b/resources/views/livewire/customer/notifications.blade.php index 46b472d0..6858eca2 100644 --- a/resources/views/livewire/customer/notifications.blade.php +++ b/resources/views/livewire/customer/notifications.blade.php @@ -1,5 +1,5 @@
-
+
Notifications Stay up to date with your account activity. @@ -44,13 +44,19 @@ {{ $notification->data['body'] }} @endif - @if (is_null($notification->read_at)) -
+
+ @if (! empty($notification->data['action_url'])) + + {{ $notification->data['action_label'] ?? 'View' }} + + @endif + + @if (is_null($notification->read_at)) Mark as read -
- @endif + @endif +
diff --git a/resources/views/livewire/team-manager.blade.php b/resources/views/livewire/team-manager.blade.php index 15269ad8..88dd3912 100644 --- a/resources/views/livewire/team-manager.blade.php +++ b/resources/views/livewire/team-manager.blade.php @@ -24,7 +24,7 @@ {{-- Seat Management --}} -
+
Seats diff --git a/tests/Feature/Notifications/NewPluginAvailableTest.php b/tests/Feature/Notifications/NewPluginAvailableTest.php index 7593b4ee..d6eb1b3c 100644 --- a/tests/Feature/Notifications/NewPluginAvailableTest.php +++ b/tests/Feature/Notifications/NewPluginAvailableTest.php @@ -89,6 +89,17 @@ public function test_mail_contains_plugin_name(): void $this->assertStringContainsString('acme/awesome-plugin', $mail->subject); } + public function test_mail_action_links_to_plugin_page(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create(['name' => 'acme/awesome-plugin']); + + $notification = new NewPluginAvailable($plugin); + $mail = $notification->toMail($user); + + $this->assertEquals(route('plugins.show', ['vendor' => 'acme', 'package' => 'awesome-plugin']), $mail->actionUrl); + } + public function test_database_notification_contains_plugin_data(): void { $user = User::factory()->create(); @@ -100,6 +111,8 @@ public function test_database_notification_contains_plugin_data(): void $this->assertEquals($plugin->id, $data['plugin_id']); $this->assertEquals('acme/awesome-plugin', $data['plugin_name']); $this->assertStringContainsString('acme/awesome-plugin', $data['title']); + $this->assertEquals(route('plugins.show', ['vendor' => 'acme', 'package' => 'awesome-plugin']), $data['action_url']); + $this->assertEquals('View Plugin', $data['action_label']); } public function test_new_users_receive_new_plugin_notifications_by_default(): void diff --git a/tests/Feature/Notifications/PluginApprovedTest.php b/tests/Feature/Notifications/PluginApprovedTest.php new file mode 100644 index 00000000..58d7d4be --- /dev/null +++ b/tests/Feature/Notifications/PluginApprovedTest.php @@ -0,0 +1,58 @@ +create(); + $plugin = Plugin::factory()->for($user)->create(['name' => 'acme/awesome-plugin']); + + $notification = new PluginApproved($plugin); + $mail = $notification->toMail($user); + + $this->assertEquals(route('plugins.show', ['vendor' => 'acme', 'package' => 'awesome-plugin']), $mail->actionUrl); + } + + public function test_database_notification_contains_action_url(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create(['name' => 'acme/awesome-plugin']); + + $notification = new PluginApproved($plugin); + $data = $notification->toArray($user); + + $this->assertEquals(route('plugins.show', ['vendor' => 'acme', 'package' => 'awesome-plugin']), $data['action_url']); + $this->assertEquals('View Plugin', $data['action_label']); + } + + public function test_mail_contains_plugin_name(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create(['name' => 'acme/awesome-plugin']); + + $notification = new PluginApproved($plugin); + $mail = $notification->toMail($user); + + $this->assertStringContainsString('acme/awesome-plugin', $mail->render()->toHtml()); + } + + public function test_via_returns_mail_and_database(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create(); + + $notification = new PluginApproved($plugin); + + $this->assertEquals(['mail', 'database'], $notification->via($user)); + } +} diff --git a/tests/Feature/Notifications/PluginRejectedTest.php b/tests/Feature/Notifications/PluginRejectedTest.php new file mode 100644 index 00000000..76b74e27 --- /dev/null +++ b/tests/Feature/Notifications/PluginRejectedTest.php @@ -0,0 +1,75 @@ +create(); + $plugin = Plugin::factory()->for($user)->create(['name' => 'acme/awesome-plugin']); + + $notification = new PluginRejected($plugin); + $mail = $notification->toMail($user); + + $this->assertEquals(route('customer.plugins.show', ['vendor' => 'acme', 'package' => 'awesome-plugin']), $mail->actionUrl); + } + + public function test_database_notification_contains_action_url(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create(['name' => 'acme/awesome-plugin']); + + $notification = new PluginRejected($plugin); + $data = $notification->toArray($user); + + $this->assertEquals(route('customer.plugins.show', ['vendor' => 'acme', 'package' => 'awesome-plugin']), $data['action_url']); + $this->assertEquals('View Plugin', $data['action_label']); + } + + public function test_mail_contains_rejection_reason(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create([ + 'name' => 'acme/awesome-plugin', + 'rejection_reason' => 'Missing license file', + ]); + + $notification = new PluginRejected($plugin); + $rendered = $notification->toMail($user)->render()->toHtml(); + + $this->assertStringContainsString('Missing license file', $rendered); + } + + public function test_database_notification_contains_rejection_reason(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create([ + 'name' => 'acme/awesome-plugin', + 'rejection_reason' => 'Missing license file', + ]); + + $notification = new PluginRejected($plugin); + $data = $notification->toArray($user); + + $this->assertEquals('Missing license file', $data['rejection_reason']); + } + + public function test_via_returns_mail_and_database(): void + { + $user = User::factory()->create(); + $plugin = Plugin::factory()->for($user)->create(); + + $notification = new PluginRejected($plugin); + + $this->assertEquals(['mail', 'database'], $notification->via($user)); + } +}