Skip to content

feat: [LAR-132] create update article action and add locale field on … #260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -40,10 +40,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 @@ -79,10 +79,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
Loading