Skip to content

Commit 182c3fd

Browse files
authored
Feature/lar 111 create edit discussion (#236)
2 parents 49c956a + 6e2c24f commit 182c3fd

File tree

56 files changed

+884
-861
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+884
-861
lines changed

app/Actions/Discussion/ConvertDiscussionToThreadAction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ final class ConvertDiscussionToThreadAction
1313
public function execute(Discussion $discussion): Thread
1414
{
1515
return DB::transaction(function () use ($discussion) {
16-
$thread = Thread::create([
16+
$thread = Thread::query()->create([
1717
'title' => $discussion->title,
1818
'slug' => $discussion->slug,
1919
'body' => $discussion->body,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Actions\Discussion;
6+
7+
use App\Gamify\Points\DiscussionCreated;
8+
use App\Models\Discussion;
9+
use Illuminate\Support\Facades\DB;
10+
11+
final class CreateOrUpdateDiscussionAction
12+
{
13+
public function handle(array $formValues, ?int $discussionId = null): Discussion
14+
{
15+
return DB::transaction(function () use ($formValues, $discussionId) {
16+
/** @var Discussion $discussion */
17+
$discussion = Discussion::query()->updateOrCreate(
18+
['id' => $discussionId],
19+
$formValues
20+
);
21+
22+
if (! $discussionId) {
23+
givePoint(new DiscussionCreated($discussion));
24+
}
25+
26+
return $discussion;
27+
});
28+
}
29+
}

app/Actions/Discussion/NotifyUsersOfThreadConversion.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ public function execute(Thread $thread): void
1616
{
1717
$usersToNotify = $thread->replies()->pluck('user_id')->unique()->toArray();
1818

19-
User::whereIn('id', $usersToNotify)->get()->each->notify(new ThreadConvertedByCreator($thread));
19+
User::query()->whereIn('id', $usersToNotify)
20+
->get()
21+
->each
22+
->notify(new ThreadConvertedByCreator($thread));
2023

21-
if (Auth::check() && Auth::user()->isAdmin()) {
24+
if (Auth::check() && (Auth::user()?->isAdmin() || Auth::user()?->isModerator())) {
2225
$thread->user->notify(new ThreadConvertedByAdmin($thread));
2326
}
2427
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Livewire\Components\Slideovers;
6+
7+
use App\Actions\Discussion\CreateOrUpdateDiscussionAction;
8+
use App\Exceptions\UnverifiedUserException;
9+
use App\Livewire\Traits\WithAuthenticatedUser;
10+
use App\Models\Discussion;
11+
use Filament\Forms;
12+
use Filament\Forms\Concerns\InteractsWithForms;
13+
use Filament\Forms\Contracts\HasForms;
14+
use Filament\Forms\Form;
15+
use Filament\Notifications\Notification;
16+
use Illuminate\Contracts\View\View;
17+
use Illuminate\Support\Facades\Auth;
18+
use Illuminate\Support\Facades\Blade;
19+
use Illuminate\Support\HtmlString;
20+
use Illuminate\Support\Str;
21+
use Laravelcm\LivewireSlideOvers\SlideOverComponent;
22+
23+
/**
24+
* @property Form $form
25+
*/
26+
final class DiscussionForm extends SlideOverComponent implements HasForms
27+
{
28+
use InteractsWithForms;
29+
use WithAuthenticatedUser;
30+
31+
public ?Discussion $discussion = null;
32+
33+
public ?array $data = [];
34+
35+
public function mount(?int $discussionId = null): void
36+
{
37+
// @phpstan-ignore-next-line
38+
$this->discussion = $discussionId
39+
? Discussion::query()->findOrFail($discussionId)
40+
: new Discussion;
41+
42+
$this->form->fill(array_merge(
43+
$this->discussion->toArray(),
44+
['user_id' => $this->discussion->user_id ?? Auth::id()]
45+
));
46+
}
47+
48+
public function form(Form $form): Form
49+
{
50+
return $form
51+
->schema([
52+
Forms\Components\Hidden::make('user_id'),
53+
Forms\Components\TextInput::make('title')
54+
->label(__('validation.attributes.title'))
55+
->helperText(__('pages/discussion.min_discussion_length'))
56+
->required()
57+
->live(onBlur: true)
58+
->afterStateUpdated(function (string $operation, $state, Forms\Set $set): void {
59+
$set('slug', Str::slug($state));
60+
})
61+
->minLength(10),
62+
Forms\Components\Hidden::make('slug'),
63+
Forms\Components\Select::make('tags')
64+
->multiple()
65+
->relationship(
66+
name: 'tags',
67+
titleAttribute: 'name',
68+
modifyQueryUsing: fn ($query) => $query->whereJsonContains('concerns', 'discussion')
69+
)
70+
->required()
71+
->minItems(1)
72+
->maxItems(3)
73+
->preload(),
74+
Forms\Components\MarkdownEditor::make('body')
75+
->toolbarButtons([
76+
'blockquote',
77+
'bold',
78+
'bulletList',
79+
'codeBlock',
80+
'link',
81+
])
82+
->label(__('validation.attributes.content'))
83+
->maxHeight('18.25rem')
84+
->required()
85+
->minLength(20),
86+
Forms\Components\Placeholder::make('')
87+
->content(fn () => new HtmlString(Blade::render(<<<'Blade'
88+
<x-torchlight />
89+
Blade))),
90+
])
91+
->statePath('data')
92+
->model($this->discussion);
93+
}
94+
95+
public function save(): void
96+
{
97+
// @phpstan-ignore-next-line
98+
if (! Auth::user()->hasVerifiedEmail()) {
99+
throw new UnverifiedUserException(
100+
message: __('notifications.exceptions.unverified_user')
101+
);
102+
}
103+
104+
if ($this->discussion?->id) {
105+
$this->authorize('update', $this->discussion);
106+
}
107+
108+
$this->validate();
109+
110+
$discussion = app(CreateOrUpdateDiscussionAction::class)->handle(
111+
formValues : $this->form->getState(),
112+
discussionId: $this->discussion?->id
113+
);
114+
115+
$this->form->model($discussion)->saveRelationships();
116+
117+
Notification::make()
118+
->title(
119+
$this->discussion?->id
120+
? __('notifications.discussion.updated')
121+
: __('notifications.discussion.created'),
122+
)
123+
->success()
124+
->send();
125+
126+
$this->redirect(route('discussions.show', ['discussion' => $discussion]), navigate: true);
127+
}
128+
129+
public static function panelMaxWidth(): string
130+
{
131+
return '2xl';
132+
}
133+
134+
public static function closePanelOnEscape(): bool
135+
{
136+
return false;
137+
}
138+
139+
public static function closePanelOnClickAway(): bool
140+
{
141+
return false;
142+
}
143+
144+
public function render(): View
145+
{
146+
return view('livewire.components.slideovers.discussion-form');
147+
}
148+
}

app/Livewire/Discussions/Create.php

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

app/Livewire/Discussions/Edit.php

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

app/Livewire/Discussions/Subscribe.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
use App\Models\Discussion;
88
use App\Models\Subscribe as SubscribeModel;
9-
use App\Policies\DiscussionPolicy;
109
use Filament\Notifications\Notification;
1110
use Illuminate\Contracts\View\View;
1211
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
@@ -27,7 +26,7 @@ final class Subscribe extends Component
2726

2827
public function subscribe(): void
2928
{
30-
$this->authorize(DiscussionPolicy::SUBSCRIBE, $this->discussion);
29+
$this->authorize('subscribe', $this->discussion);
3130

3231
$subscribe = new SubscribeModel;
3332
$subscribe->uuid = Uuid::uuid4()->toString();
@@ -46,7 +45,7 @@ public function subscribe(): void
4645

4746
public function unsubscribe(): void
4847
{
49-
$this->authorize(DiscussionPolicy::UNSUBSCRIBE, $this->discussion);
48+
$this->authorize('unsubscribe', $this->discussion);
5049

5150
$this->discussion->subscribes()
5251
->where('user_id', Auth::id())

app/Livewire/Modals/ConvertDiscussion.php

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

0 commit comments

Comments
 (0)