From 5e49372443a254839ca06a1d5890651b6e8332bc Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 4 Mar 2024 20:05:27 -0300 Subject: [PATCH] notification management --- app/Http/Controllers/ProfileController.php | 1 + app/Http/Controllers/SettingsController.php | 24 +++++++++++ app/Http/Controllers/WishController.php | 2 +- .../Controllers/WishlistCommentController.php | 2 +- app/Models/User.php | 8 +++- .../2014_10_12_000000_create_users_table.php | 1 + resources/views/profile/edit.blade.php | 6 +++ .../partials/update-settings-form.blade.php | 43 +++++++++++++++++++ routes/web.php | 2 + tests/Feature/GuestWishlistTest.php | 6 --- tests/Feature/ProfileTest.php | 20 +++++++++ tests/Feature/WishlistNotificationTest.php | 26 +++++++++++ 12 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 app/Http/Controllers/SettingsController.php create mode 100644 resources/views/profile/partials/update-settings-form.blade.php diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index a48eb8d..bfa2817 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -18,6 +18,7 @@ public function edit(Request $request): View { return view('profile.edit', [ 'user' => $request->user(), + 'settings' => $request->user()->settings, ]); } diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php new file mode 100644 index 0000000..2f188a1 --- /dev/null +++ b/app/Http/Controllers/SettingsController.php @@ -0,0 +1,24 @@ +user()->settings; + $settings['notification']['wishlist-comment-created'] = (bool) $request->request->get('notification-wishlist-comment-created'); + $settings['notification']['wish-created'] = (bool) $request->request->get('notification-wish-created'); + $request->user()->settings = $settings; + $request->user()->save(); + + return Redirect::route('profile.edit')->with('status', 'settings-updated'); + } +} diff --git a/app/Http/Controllers/WishController.php b/app/Http/Controllers/WishController.php index d9d48f6..6463775 100644 --- a/app/Http/Controllers/WishController.php +++ b/app/Http/Controllers/WishController.php @@ -26,7 +26,7 @@ public function store(Request $request, Wishlist $wishlist) 'description' => ['nullable', 'string', 'max:2000'], ])); - Notification::send($wishlist->viewers, new WishCreatedNotification($wish)); + Notification::send($wishlist->viewers->filter(fn ($user) => $user->settings['notification']['wish-created']), new WishCreatedNotification($wish)); return to_route('wishlists.show', $wishlist); } diff --git a/app/Http/Controllers/WishlistCommentController.php b/app/Http/Controllers/WishlistCommentController.php index 6b03a08..b71758b 100644 --- a/app/Http/Controllers/WishlistCommentController.php +++ b/app/Http/Controllers/WishlistCommentController.php @@ -36,7 +36,7 @@ public function store(Request $request, Wishlist $wishlist) $comment = $wishlist->addComment($request->comment, $request->user()); - $watchers = $wishlist->viewers->push($wishlist->user)->reject(fn ($user) => $user->is($request->user())); + $watchers = $wishlist->viewers->push($wishlist->user)->reject(fn ($user) => $user->is($request->user()) || !$user->settings['notification']['wishlist-comment-created']); Notification::send($watchers, new WishlistCommentCreatedNotification($comment)); diff --git a/app/Models/User.php b/app/Models/User.php index fe1901f..b0254ba 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -16,6 +16,7 @@ class User extends Authenticatable 'name', 'email', 'password', + 'settings' ]; protected $hidden = [ @@ -26,6 +27,11 @@ class User extends Authenticatable protected $casts = [ 'email_verified_at' => 'datetime', 'password' => 'hashed', + 'settings' => 'array' + ]; + + protected $attributes = [ + 'settings' => '{"notification":{"wishlist-comment-created":true,"wish-created":true}}' ]; public function wishlists() @@ -41,7 +47,7 @@ public function joinedWishlists() protected function avatarUrl(): Attribute { return Attribute::make( - get: fn ($value, $attributes) => "https://unavatar.io/{$attributes['email']}?".http_build_query([ + get: fn ($value, $attributes) => "https://unavatar.io/{$attributes['email']}?" . http_build_query([ 'fallback' => "https://ui-avatars.com/api/{$attributes['name']}/32/bae6fd/0c4a6e", ]) )->shouldCache(); diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 444fafb..1bd6f2a 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -17,6 +17,7 @@ public function up(): void $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); + $table->json('settings')->nullable(); $table->rememberToken(); $table->timestamps(); }); diff --git a/resources/views/profile/edit.blade.php b/resources/views/profile/edit.blade.php index ffc6652..6f1bd63 100644 --- a/resources/views/profile/edit.blade.php +++ b/resources/views/profile/edit.blade.php @@ -18,6 +18,12 @@ +
+
+ @include('profile.partials.update-settings-form') +
+
+
@include('profile.partials.delete-user-form') diff --git a/resources/views/profile/partials/update-settings-form.blade.php b/resources/views/profile/partials/update-settings-form.blade.php new file mode 100644 index 0000000..0c2c99b --- /dev/null +++ b/resources/views/profile/partials/update-settings-form.blade.php @@ -0,0 +1,43 @@ +
+
+

+ {{ __('Settings') }} +

+ +

+ {{ __('Configure which notifications you want to receive') }} +

+
+ +
+ + + + + + + + + +
+ +
+ {{ __('Save changes') }} + + @if (session('status') === 'settings-updated') +

{{ __('Saved.') }}

+ @endif +
+
+
+ diff --git a/routes/web.php b/routes/web.php index 7a4bcd9..bd91a5c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -11,6 +11,7 @@ use App\Http\Controllers\Guest\GuestWishController; use App\Http\Controllers\Guest\GuestWishlistController; use App\Http\Controllers\Guest\GuestSortWishlistController; +use App\Http\Controllers\SettingsController; use App\Models\Wishlist; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; @@ -36,6 +37,7 @@ Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit'); Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update'); Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); + Route::put('/settings', [SettingsController::class, 'update'])->name('settings.update'); Route::get('/wishlists', [WishlistController::class, 'index'])->name('wishlists.index'); Route::get('/wishlists/create', [WishlistController::class, 'create'])->name('wishlists.create')->can('create', Wishlist::class); diff --git a/tests/Feature/GuestWishlistTest.php b/tests/Feature/GuestWishlistTest.php index ef01367..a50ba84 100644 --- a/tests/Feature/GuestWishlistTest.php +++ b/tests/Feature/GuestWishlistTest.php @@ -1,11 +1,5 @@ 'My wishlist', - 'id' => 0, - 'wishes' => [] -]; - test('guest see the default wishlist', function() { $response = $this->get(route('guests.wishlists.show')); diff --git a/tests/Feature/ProfileTest.php b/tests/Feature/ProfileTest.php index efd802f..e1686b2 100644 --- a/tests/Feature/ProfileTest.php +++ b/tests/Feature/ProfileTest.php @@ -83,3 +83,23 @@ $this->assertNotNull($user->fresh()); }); + +test('settings can be updated', function () { + $user = User::factory()->create(); + + $response = $this + ->actingAs($user) + ->put(route('settings.update'), [ + 'notification-wishlist-comment-created' => 'notification-wishlist-comment-created', + 'notification-wish-created' => null, + ]); + + $response + ->assertSessionHasNoErrors() + ->assertRedirect(route('profile.edit')); + + $user->refresh(); + + $this->assertSame(true, $user->settings['notification']['wishlist-comment-created']); + $this->assertSame(false, $user->settings['notification']['wish-created']); +}); \ No newline at end of file diff --git a/tests/Feature/WishlistNotificationTest.php b/tests/Feature/WishlistNotificationTest.php index f8bec4f..efdcd69 100644 --- a/tests/Feature/WishlistNotificationTest.php +++ b/tests/Feature/WishlistNotificationTest.php @@ -27,3 +27,29 @@ function (WishCreatedNotification $notification) { } ); }); + +test('viewers are not notified when a wish is added to a wishlist if settings is off', function () { + Notification::fake(); + + $wishlist = Wishlist::factory()->create(); + $viewer = User::factory()->create(); + $settings = $viewer->settings; + $settings['notification']['wish-created'] = false; + $viewer->settings = $settings; + $viewer->save(); + $wishlist->viewers()->attach($viewer); + + $this->actingAs($wishlist->user); + $this->post(route('wishes.create', $wishlist), [ + 'name' => 'New Wish', + 'url' => 'https://imacrayon.com', + 'description' => 'Test description.', + ]); + + Notification::assertNotSentTo( + $viewer, + function (WishCreatedNotification $notification) { + return $notification->wish->id === Wish::first()->id; + } + ); +}); \ No newline at end of file