Skip to content

Commit d41b68d

Browse files
committed
feat:(LAR-105) add transform a discussion to a thread
1 parent 9139b82 commit d41b68d

14 files changed

+182
-136
lines changed

app/Actions/Discussion/ConvertDiscussionToThreadAction.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace App\Actions\Discussion;
46

57
use App\Models\Discussion;
68
use App\Models\Thread;
7-
use App\Notifications\NotifyUserConvertionDiscussionToThread;
89
use Illuminate\Support\Facades\DB;
910

10-
class ConvertDiscussionToThreadAction
11+
final class ConvertDiscussionToThreadAction
1112
{
1213
public function execute(Discussion $discussion, bool $isAdmin = false): Thread
1314
{
14-
return DB::transaction(function () use ($discussion) {
15+
return DB::transaction(function () use ($discussion, $isAdmin) {
1516
$thread = Thread::create([
1617
'title' => $discussion->title,
1718
'slug' => $discussion->slug,
@@ -22,13 +23,13 @@ public function execute(Discussion $discussion, bool $isAdmin = false): Thread
2223
]);
2324

2425
$discussion->replies()->update([
25-
'replyable_type' => Thread::class,
26+
'replyable_type' => 'thread',
2627
'replyable_id' => $thread->id,
2728
]);
2829

2930
$discussion->delete();
3031

31-
app(NotifyUserConvertionDiscussionToThread::class)->execute($thread, $isAdmin);
32+
app(NotifyUsersOfThreadConversion::class)->execute($thread, $isAdmin);
3233

3334
return $thread;
3435
});
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace App\Actions\Discussion;
46

57
use App\Models\Thread;
8+
use App\Models\User;
69
use App\Notifications\ThreadConvertedByAdmin;
710
use App\Notifications\ThreadConvertedByCreator;
8-
use Illuminate\Support\Facades\Mail;
911

10-
class NotifyUsersOfThreadConversion
12+
final class NotifyUsersOfThreadConversion
1113
{
1214
public function execute(Thread $thread, bool $isAdmin = false): void
1315
{
14-
$usersToNotify = $thread->replies->pluck('user')->unique();
16+
$usersToNotify = $thread->replies()->pluck('user_id')->unique()->toArray();
1517

16-
// ToDo: send mail to the replying user with this class notification ThreadConvertedByCreator
18+
User::whereIn('id', $usersToNotify)->get()->each->notify(new ThreadConvertedByCreator($thread));
1719

1820
if ($isAdmin) {
1921
$creator = $thread->user;
20-
// ToDo: send mail to the creator with this class notification ThreadConvertedByAdmin
22+
23+
$creator->notify(new ThreadConvertedByAdmin($thread));
2124
}
2225
}
2326
}

app/Livewire/Discussions/ConvertedToThread.php

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Livewire\Modals;
6+
7+
use App\Actions\Discussion\ConvertDiscussionToThreadAction;
8+
use App\Models\Discussion;
9+
use App\Policies\DiscussionPolicy;
10+
use Illuminate\Contracts\View\View;
11+
use Illuminate\Support\Facades\Auth;
12+
use LivewireUI\Modal\ModalComponent;
13+
14+
final class ConvertDiscussion extends ModalComponent
15+
{
16+
public int $discussionId;
17+
18+
public function save(): void
19+
{
20+
$discussion = Discussion::findOrFail($this->discussionId);
21+
22+
$this->authorize(DiscussionPolicy::CONVERTEDTOTHREAD, $discussion);
23+
24+
$thread = app(ConvertDiscussionToThreadAction::class)->execute($discussion, Auth::user()->isAdmin());
25+
26+
$this->redirectRoute('forum.show', $thread, navigate: true);
27+
}
28+
29+
public function render(): View
30+
{
31+
return view('livewire.modals.convert-discussion');
32+
}
33+
}

app/Notifications/ThreadConvertedByAdmin.php

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,16 @@
44

55
namespace App\Notifications;
66

7+
use App\Models\Thread;
78
use Illuminate\Bus\Queueable;
8-
use Illuminate\Contracts\Queue\ShouldQueue;
99
use Illuminate\Notifications\Messages\MailMessage;
1010
use Illuminate\Notifications\Notification;
1111

1212
final class ThreadConvertedByAdmin extends Notification
1313
{
1414
use Queueable;
1515

16-
public function __construct()
17-
{
18-
//
19-
}
16+
public function __construct(public Thread $thread) {}
2017

2118
/**
2219
* Get the notification's delivery channels.
@@ -33,18 +30,12 @@ public function via(object $notifiable): array
3330
*/
3431
public function toMail(object $notifiable): MailMessage
3532
{
36-
return (new MailMessage)->markdown('emails.notify-creator-for-thread-conversion');
37-
}
38-
39-
/**
40-
* Get the array representation of the notification.
41-
*
42-
* @return array<string, mixed>
43-
*/
44-
public function toArray(object $notifiable): array
45-
{
46-
return [
47-
//
48-
];
33+
return (new MailMessage)
34+
->subject('Discussion Converted by Admin')
35+
->greeting('Hello!')
36+
->line('An admin has converted a discussion to a thread.')
37+
->line('Thread Title: '.$this->thread->title)
38+
->action('View Thread', route('forum.show', $this->thread))
39+
->line('This action was performed by an administrator.');
4940
}
5041
}

app/Notifications/ThreadConvertedByCreator.php

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,16 @@
44

55
namespace App\Notifications;
66

7+
use App\Models\Thread;
78
use Illuminate\Bus\Queueable;
8-
use Illuminate\Contracts\Queue\ShouldQueue;
99
use Illuminate\Notifications\Messages\MailMessage;
1010
use Illuminate\Notifications\Notification;
1111

1212
final class ThreadConvertedByCreator extends Notification
1313
{
1414
use Queueable;
1515

16-
public function __construct()
17-
{
18-
//
19-
}
16+
public function __construct(public Thread $thread) {}
2017

2118
/**
2219
* Get the notification's delivery channels.
@@ -33,18 +30,11 @@ public function via(object $notifiable): array
3330
*/
3431
public function toMail(object $notifiable): MailMessage
3532
{
36-
return (new MailMessage)->markdown('emails.notification-user-to-thread-conversion');
37-
}
38-
39-
/**
40-
* Get the array representation of the notification.
41-
*
42-
* @return array<string, mixed>
43-
*/
44-
public function toArray(object $notifiable): array
45-
{
46-
return [
47-
//
48-
];
33+
return (new MailMessage)
34+
->subject(__('Discussion Converted to Thread'))
35+
->line('A discussion you participated in has been converted to a thread.')
36+
->line('Thread Title: '.$this->thread->title)
37+
->action('View Thread', route('forum.show', $this->thread))
38+
->line('Thank you for your participation!');
4939
}
5040
}

app/Policies/DiscussionPolicy.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ final class DiscussionPolicy
2222

2323
public const UNSUBSCRIBE = 'unsubscribe';
2424

25-
public const string CONVERTEDTOTHREAD = 'convertedToThread';
25+
public const CONVERTEDTOTHREAD = 'convertedToThread';
2626

2727
public function create(User $user): bool
2828
{
@@ -54,13 +54,13 @@ public function unsubscribe(User $user, Discussion $discussion): bool
5454
return $discussion->hasSubscriber($user);
5555
}
5656

57-
public function convertedToThread(User $user, Discussion $discussion): bool
57+
public function report(User $user, Discussion $discussion): bool
5858
{
59-
return $discussion->isAuthoredBy($user) || $user->isModerator() || $user->isAdmin();
59+
return $user->hasVerifiedEmail() && ! $discussion->isAuthoredBy($user);
6060
}
6161

62-
public function report(User $user, Discussion $discussion): bool
62+
public function convertedToThread(User $user, Discussion $discussion): bool
6363
{
64-
return $user->hasVerifiedEmail() && ! $discussion->isAuthoredBy($user);
64+
return $discussion->isAuthoredBy($user) || $user->isAdmin();
6565
}
6666
}

resources/views/emails/notification-user-to-thread-conversion.blade.php

Lines changed: 0 additions & 12 deletions
This file was deleted.

resources/views/emails/notify-creator-for-thread-conversion.blade.php

Lines changed: 0 additions & 12 deletions
This file was deleted.

resources/views/livewire/discussions/converted-to-thread.blade.php

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<x-modal
2+
header-classes="p-4 border-b border-gray-100 sm:px-6 sm:py-4"
3+
content-classes="relative p-4 flex-1 sm:max-h-[500px] sm:px-6 sm:px-5"
4+
footer-classes="px-4 py-3 border-t border-gray-100 sm:px-6 sm:flex sm:flex-row-reverse"
5+
form-action="save"
6+
>
7+
<x-slot name="title">
8+
{{ __("Confirmez la convertion") }}
9+
</x-slot>
10+
11+
<div class="space-y-4 pb-5">
12+
<div class="grid grid-cols-2 gap-4">
13+
<div class="space-y-2">
14+
<x-slot name="content">
15+
{{ __("Voulez-vous vraiment convertir cette discussion en thread ?") }}
16+
</x-slot>
17+
</div>
18+
</div>
19+
</div>
20+
21+
<x-slot name="buttons">
22+
<x-buttons.submit
23+
:title="__('Confirmer')"
24+
wire:loading.attr="data-loading"
25+
class="w-full sm:ml-3 sm:w-auto"
26+
/>
27+
<x-buttons.default
28+
type="button"
29+
wire:click="$dispatch('closeModal')"
30+
class="w-full px-4 py-2 mt-3 text-sm sm:mt-0 sm:w-auto"
31+
>
32+
{{ __('Annuler') }}
33+
</x-buttons.default>
34+
</x-slot>
35+
</x-modal>

resources/views/livewire/pages/discussions/single-discussion.blade.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,21 @@ class="font-sans text-sm leading-5 text-gray-500 dark:text-gray-400 hover:underl
101101
</x-link>
102102
<span class="font-medium text-gray-500 dark:text-gray-400">·</span>
103103
<button
104-
onclick="Livewire.dispatch('openModal', {component: 'modals.delete-discussion', arguments: {{ json_encode([$discussion->id]) }})"
104+
onclick="Livewire.dispatch('openModal', {component: 'modals.delete-discussion', arguments: {{ json_encode([$discussion->id]) }}})"
105105
type="button"
106106
class="font-sans text-sm leading-5 text-red-500 hover:underline focus:outline-none"
107107
>
108108
{{ __('Supprimer') }}
109109
</button>
110+
@can('convertedToThread', $discussion)
111+
<span class="font-medium text-gray-500 dark:text-gray-400">·</span>
112+
<button
113+
onclick="Livewire.dispatch('openModal', {component: 'modals.convert-discussion', arguments: { discussionId: {{ $discussion->id }} }})"
114+
class="font-sans text-sm leading-5 text-gray-500 dark:text-gray-400 hover:underline focus:outline-none hover:po"
115+
>
116+
{{ __('Convertir en Thread') }}
117+
</button>
118+
@endcan
110119
</div>
111120
@endcan
112121
</div>
@@ -120,7 +129,6 @@ class="font-sans text-sm leading-5 text-red-500 hover:underline focus:outline-no
120129
</p>
121130
@auth
122131
<livewire:discussions.subscribe :discussion="$discussion" />
123-
<livewire:discussions.converted-to-thread :discussion="$discussion" />
124132
@endauth
125133
</div>
126134

0 commit comments

Comments
 (0)