Skip to content

Commit

Permalink
feat: [LAR-132] create update article action and add locale field on … (
Browse files Browse the repository at this point in the history
  • Loading branch information
cybersoldattech authored Dec 21, 2024
2 parents e60b432 + 96c998e commit 7efd57d
Show file tree
Hide file tree
Showing 23 changed files with 240 additions and 66 deletions.
23 changes: 12 additions & 11 deletions app/Actions/Article/CreateArticleAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@

namespace App\Actions\Article;

use App\Data\CreateArticleData;
use App\Data\ArticleData;
use App\Models\Article;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;

final class CreateArticleAction
{
public function execute(CreateArticleData $articleData): Article
public function execute(ArticleData $articleData): Article
{
if ($articleData->published_at) {
$articleData->published_at = new Carbon(
Expand All @@ -21,20 +20,22 @@ public function execute(CreateArticleData $articleData): Article
);
}

/** @var User $author */
$author = Auth::user();
if ($articleData->submitted_at) {
$articleData->submitted_at = new Carbon(
time: $articleData->submitted_at,
timezone: config('app.timezone')
);
}

/** @var Article $article */
$article = Article::query()->create([
// @phpstan-ignore-next-line
return Article::query()->create([
'title' => $articleData->title,
'slug' => $articleData->slug,
'body' => $articleData->body,
'published_at' => $articleData->published_at,
'submitted_at' => $articleData->is_draft ? null : now(),
'submitted_at' => $articleData->submitted_at,
'canonical_url' => $articleData->canonical_url,
'user_id' => $author->id,
'user_id' => Auth::id(),
]);

return $article;
}
}
40 changes: 40 additions & 0 deletions app/Actions/Article/UpdateArticleAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace App\Actions\Article;

use App\Data\ArticleData;
use App\Exceptions\CannotUpdateApprovedArticle;
use App\Models\Article;
use Carbon\Carbon;

final class UpdateArticleAction
{
public function execute(ArticleData $articleData, Article $article): Article
{
if ($article->isApproved()) {
throw new CannotUpdateApprovedArticle(__('notifications.exceptions.approved_article'));
}

if ($articleData->published_at) {
$articleData->published_at = new Carbon(
time: $articleData->published_at,
timezone: config('app.timezone')
);
}

if ($articleData->submitted_at) {
$articleData->submitted_at = new Carbon(
time: $articleData->submitted_at,
timezone: config('app.timezone')
);
}

$article->update($articleData->toArray());

$article->refresh();

return $article;
}
}
9 changes: 5 additions & 4 deletions app/Data/CreateArticleData.php → app/Data/ArticleData.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
use Carbon\Carbon;
use Spatie\LaravelData\Data;

final class CreateArticleData extends Data
final class ArticleData extends Data
{
public function __construct(
public string $title,
public string $slug,
public string $body,
public string $canonical_url,
public ?Carbon $published_at,
public bool $is_draft = false,
public string $locale,
public ?string $canonical_url = null,
public ?Carbon $published_at = null,
public ?Carbon $submitted_at = null,
) {}
}
7 changes: 7 additions & 0 deletions app/Exceptions/CannotUpdateApprovedArticle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

declare(strict_types=1);

namespace App\Exceptions;

final class CannotUpdateApprovedArticle extends \Exception {}
44 changes: 28 additions & 16 deletions app/Livewire/Components/Slideovers/ArticleForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
namespace App\Livewire\Components\Slideovers;

use App\Actions\Article\CreateArticleAction;
use App\Data\CreateArticleData;
use App\Actions\Article\UpdateArticleAction;
use App\Data\ArticleData;
use App\Exceptions\UnverifiedUserException;
use App\Livewire\Traits\WithAuthenticatedUser;
use App\Models\Article;
Expand Down Expand Up @@ -44,6 +45,7 @@ public function mount(?int $articleId = null): void
$this->form->fill(array_merge($this->article->toArray(), [
'is_draft' => ! $this->article->published_at, // @phpstan-ignore-line
'published_at' => $this->article->published_at, // @phpstan-ignore-line
'locale' => $this->article->locale ?? app()->getLocale(),
]));
}

Expand Down Expand Up @@ -114,6 +116,11 @@ public function form(Form $form): Form
->required()
->minItems(1)
->maxItems(3),
Forms\Components\ToggleButtons::make('locale')
->label(__('validation.attributes.locale'))
->options(['en' => 'En', 'fr' => 'Fr'])
->helperText(__('global.locale_help'))
->grouped(),
])
->columnSpan(1),
Forms\Components\Group::make()
Expand Down Expand Up @@ -163,42 +170,47 @@ public function save(): void

$this->validate();

$validated = $this->form->getState();
$state = $this->form->getState();

$publishedFields = [
'published_at' => data_get($state, 'published_at')
? new Carbon(data_get($state, 'published_at'))
: null,
'submitted_at' => data_get($state, 'is_draft') ? null : now(),
];

if ($this->article?->id) {
$this->article->update(array_merge($validated, [
'submitted_at' => $validated['is_draft'] ? null : now(),
]));
$this->form->model($this->article)->saveRelationships();
$this->article->fresh();
$article = app(UpdateArticleAction::class)->execute(
articleData: ArticleData::from(array_merge($state, $publishedFields)),
article: $this->article
);

Notification::make()
->title(
$this->article->submitted_at
$article->submitted_at
? __('notifications.article.submitted')
: __('notifications.article.updated'),
)
->success()
->send();
} else {
$article = app(CreateArticleAction::class)->execute(CreateArticleData::from(array_merge($validated, [
'published_at' => array_key_exists('published_at', $validated)
? new Carbon($validated['published_at'])
: null,
])));
$this->form->model($article)->saveRelationships();
$article = app(CreateArticleAction::class)->execute(
ArticleData::from(array_merge($state, $publishedFields))
);

Notification::make()
->title(
$validated['is_draft'] === false
data_get($state, 'is_draft') === false
? __('notifications.article.submitted')
: __('notifications.article.created'),
)
->success()
->send();
}

$this->redirect(route('articles.show', ['article' => $article ?? $this->article]), navigate: true);
$this->form->model($article)->saveRelationships();

$this->redirect(route('articles.show', ['article' => $article]), navigate: true);
}

public function render(): View
Expand Down
13 changes: 9 additions & 4 deletions app/Livewire/Components/Slideovers/DiscussionForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public function mount(?int $discussionId = null): void
? Discussion::query()->findOrFail($discussionId)
: new Discussion;

$this->form->fill(array_merge(
$this->discussion->toArray(),
['user_id' => $this->discussion->user_id ?? Auth::id()]
));
$this->form->fill(array_merge($this->discussion->toArray(), [
'user_id' => $this->discussion->user_id ?? Auth::id(),
'locale' => $this->discussion->locale ?? app()->getLocale(),
]));
}

public function form(Form $form): Form
Expand Down Expand Up @@ -71,6 +71,11 @@ public function form(Form $form): Form
->minItems(1)
->maxItems(3)
->preload(),
Forms\Components\ToggleButtons::make('locale')
->label(__('validation.attributes.locale'))
->options(['en' => 'En', 'fr' => 'Fr'])
->helperText(__('global.locale_help'))
->grouped(),
Forms\Components\MarkdownEditor::make('body')
->toolbarButtons([
'blockquote',
Expand Down
15 changes: 10 additions & 5 deletions app/Livewire/Components/Slideovers/ThreadForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public function mount(?int $threadId = null): void
? Thread::query()->findOrFail($threadId)
: new Thread;

$this->form->fill(array_merge(
$this->thread->toArray(),
['user_id' => $this->thread->user_id ?? Auth::id()]
));
$this->form->fill(array_merge($this->thread->toArray(), [
'user_id' => $this->thread->user_id ?? Auth::id(),
'locale' => $this->thread->locale ?? app()->getLocale(),
]));
}

public static function panelMaxWidth(): string
Expand Down Expand Up @@ -78,10 +78,15 @@ public function form(Form $form): Form
Forms\Components\Select::make('channels')
->multiple()
->relationship(titleAttribute: 'name')
->searchable()
->preload()
->required()
->minItems(1)
->maxItems(3),
Forms\Components\ToggleButtons::make('locale')
->label(__('validation.attributes.locale'))
->options(['en' => 'En', 'fr' => 'Fr'])
->helperText(__('global.locale_help'))
->grouped(),
Forms\Components\MarkdownEditor::make('body')
->fileAttachmentsDisk('public')
->toolbarButtons([
Expand Down
18 changes: 10 additions & 8 deletions app/Models/Article.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@
* @property string | null $canonical_url
* @property int | null $tweet_id
* @property int $user_id
* @property string | null $locale
* @property-read User $user
* @property \Illuminate\Support\Carbon | null $published_at
* @property \Illuminate\Support\Carbon | null $submitted_at
* @property \Illuminate\Support\Carbon | null $approved_at
* @property \Illuminate\Support\Carbon | null $shared_at
* @property \Illuminate\Support\Carbon | null $declined_at
* @property \Illuminate\Support\Carbon | null $sponsored_at
* @property \Illuminate\Support\Carbon $created_at
* @property \Illuminate\Support\Carbon $updated_at
* @property \Carbon\Carbon | null $published_at
* @property \Carbon\Carbon | null $submitted_at
* @property \Carbon\Carbon | null $approved_at
* @property \Carbon\Carbon | null $shared_at
* @property \Carbon\Carbon | null $declined_at
* @property \Carbon\Carbon | null $sponsored_at
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property \Illuminate\Database\Eloquent\Collection | Tag[] $tags
*/
final class Article extends Model implements HasMedia, ReactableInterface, Viewable
Expand Down Expand Up @@ -69,6 +70,7 @@ final class Article extends Model implements HasMedia, ReactableInterface, Viewa
'shared_at',
'sponsored_at',
'published_at',
'locale',
];

protected $casts = [
Expand Down
2 changes: 2 additions & 0 deletions app/Models/Discussion.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* @property string $body
* @property bool $locked
* @property bool $is_pinned
* @property string | null $locale
* @property int $user_id
* @property-read int $count_all_replies_with_child
* @property Carbon $created_at
Expand Down Expand Up @@ -62,6 +63,7 @@ final class Discussion extends Model implements ReactableInterface, ReplyInterfa
'user_id',
'is_pinned',
'locked',
'locale',
];

protected $casts = [
Expand Down
2 changes: 2 additions & 0 deletions app/Models/Thread.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* @property int $user_id
* @property int $solution_reply_id
* @property bool $locked
* @property string | null $locale
* @property Carbon | null $last_posted_at
* @property Carbon $created_at
* @property Carbon $updated_at
Expand Down Expand Up @@ -73,6 +74,7 @@ final class Thread extends Model implements Feedable, ReactableInterface, ReplyI
'body',
'slug',
'user_id',
'locale',
];

protected $casts = [
Expand Down
22 changes: 22 additions & 0 deletions database/factories/ArticleFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,28 @@ public function definition(): array
'title' => $this->faker->sentence(),
'body' => $this->faker->paragraphs(3, true),
'slug' => $this->faker->unique()->slug(),
'locale' => $this->faker->randomElement(['en', 'fr']),
];
}

public function approved(): self
{
return $this->state(function (array $attributes): array {
return [
'published_at' => now()->addDays(2),
'submitted_at' => now(),
'approved_at' => now(),
];
});
}

public function submitted(): self
{
return $this->state(function (array $attributes): array {
return [
'submitted_at' => now(),
'published_at' => now()->addDay(),
];
});
}
}
10 changes: 10 additions & 0 deletions database/factories/TagFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@ public function definition(): array
'concerns' => ['post', 'discussion', 'tutorial'],
];
}

public function article(): self
{
return $this->state(['concerns' => ['post', 'tutorial']]);
}

public function discussion(): self
{
return $this->state(['concerns' => ['discussion']]);
}
}
1 change: 1 addition & 0 deletions lang/en/global.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,6 @@
'website' => 'Website',
'characters' => ':number characters',
'like' => ':count like',
'locale_help' => 'The language in which your content will be available on the site.',

];
1 change: 1 addition & 0 deletions lang/en/notifications.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'exceptions' => [
'unverified_user' => 'You are not authorized to do this. Your e-mail is not verified',
'spam_exist' => 'Spam already reported.',
'approved_article' => 'An approved article cannot be updated.',
],

'reply' => [
Expand Down
Loading

0 comments on commit 7efd57d

Please sign in to comment.