Skip to content

Commit d5b8fd9

Browse files
authored
Merge pull request #40 from laravelcm/39-update-articles-process
39 update articles process
2 parents edb3ff6 + ef07125 commit d5b8fd9

25 files changed

+299
-41
lines changed

app/Http/Controllers/ArticlesController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Http\Controllers;
44

55
use App\Models\Article;
6+
use App\Models\User;
67
use App\Policies\ArticlePolicy;
78
use Illuminate\Support\Facades\Auth;
89
use Illuminate\Support\Facades\Cache;
@@ -21,6 +22,7 @@ public function index()
2122

2223
public function show(Article $article)
2324
{
25+
/** @var User $user */
2426
$user = Auth::user();
2527

2628
views($article)->record();

app/Http/Controllers/User/DashboardController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ public function dashboard()
1313
return view('user.dashboard', [
1414
'user' => $user = User::scopes('withCounts')->find(Auth::id()),
1515
'articles' => $user->articles()
16-
->orderByDesc('submitted_at')
1716
->orderByDesc('created_at')
17+
->orderBy('submitted_at')
1818
->paginate(5),
1919
]);
2020
}

app/Http/Livewire/Articles/Create.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
use App\Gamify\Points\PostCreated;
66
use App\Models\Article;
77
use App\Models\Tag;
8+
use App\Models\User;
9+
use App\Notifications\SendSubmittedArticle;
810
use App\Traits\WithArticleAttributes;
911
use App\Traits\WithTagsAssociation;
1012
use Illuminate\Support\Facades\Auth;
13+
use Illuminate\Support\Facades\Notification;
1114
use Livewire\Component;
1215
use Livewire\WithFileUploads;
1316

@@ -19,9 +22,9 @@ class Create extends Component
1922

2023
public function mount()
2124
{
25+
/** @var User $user */
2226
$user = Auth::user();
2327

24-
$this->submitted = ! $user->hasAnyRole(['admin', 'moderator']);
2528
$this->submitted_at = $user->hasAnyRole(['admin', 'moderator']) ? now() : null;
2629
$this->approved_at = $user->hasAnyRole(['admin', 'moderator']) ? now() : null;
2730
}
@@ -37,23 +40,18 @@ public function submit()
3740
$this->store();
3841
}
3942

40-
public function draft()
41-
{
42-
$this->submitted = false;
43-
$this->store();
44-
}
45-
4643
public function store()
4744
{
4845
$this->validate();
4946

47+
/** @var User $user */
5048
$user = Auth::user();
5149

50+
/** @var Article $article */
5251
$article = Article::create([
5352
'title' => $this->title,
5453
'slug' => $this->slug,
5554
'body' => $this->body,
56-
'submitted' => $this->submitted,
5755
'submitted_at' => $this->submitted_at,
5856
'approved_at' => $this->approved_at,
5957
'show_toc' => $this->show_toc,
@@ -69,8 +67,11 @@ public function store()
6967
$article->addMedia($this->file->getRealPath())->toMediaCollection('media');
7068
}
7169

72-
if ($this->submitted) {
73-
// Envoi du mail a l'admin pour la validation de l'article
70+
if ($article->submitted_at) {
71+
// Envoi du mail à l'admin pour la validation de l'article.
72+
$admin = User::findByEmailAddress('monneylobe@gmail.com');
73+
Notification::send($admin, new SendSubmittedArticle($article));
74+
7475
session()->flash('status', 'Merci d\'avoir soumis votre article. Vous aurez des nouvelles que lorsque nous accepterons votre article.');
7576
}
7677

app/Http/Livewire/Articles/Edit.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
use App\Models\Article;
66
use App\Models\Tag;
7+
use App\Models\User;
8+
use App\Notifications\SendSubmittedArticle;
79
use App\Traits\WithArticleAttributes;
810
use App\Traits\WithTagsAssociation;
11+
use Illuminate\Support\Facades\Auth;
12+
use Illuminate\Support\Facades\Cache;
13+
use Illuminate\Support\Facades\Notification;
914
use Livewire\Component;
1015
use Livewire\WithFileUploads;
1116

@@ -15,6 +20,7 @@ class Edit extends Component
1520

1621
public Article $article;
1722
public ?string $preview = null;
23+
public bool $alreadySubmitted = false;
1824

1925
protected $listeners = ['markdown-x:update' => 'onMarkdownUpdate'];
2026

@@ -25,6 +31,7 @@ public function mount(Article $article)
2531
$this->body = $article->body;
2632
$this->slug = $article->slug;
2733
$this->show_toc = $article->show_toc;
34+
$this->submitted_at = $article->submitted_at;
2835
$this->canonical_url = $article->originalUrl();
2936
$this->preview = $article->getFirstMediaUrl('media');
3037
$this->associateTags = $this->tags_selected = old('tags', $article->tags()->pluck('id')->toArray());
@@ -35,6 +42,13 @@ public function onMarkdownUpdate(string $content)
3542
$this->body = $content;
3643
}
3744

45+
public function submit()
46+
{
47+
$this->alreadySubmitted = $this->article->submitted_at !== null;
48+
$this->submitted_at = $this->article->submitted_at ?? now();
49+
$this->store();
50+
}
51+
3852
public function store()
3953
{
4054
$this->save();
@@ -44,12 +58,16 @@ public function save()
4458
{
4559
$this->validate();
4660

61+
/** @var User $user */
62+
$user = Auth::user();
63+
4764
$this->article->update([
4865
'title' => $this->title,
4966
'slug' => $this->slug,
5067
'body' => $this->body,
5168
'show_toc' => $this->show_toc,
5269
'canonical_url' => $this->canonical_url,
70+
'submitted_at' => $this->submitted_at,
5371
]);
5472

5573
$this->article->syncTags($this->associateTags);
@@ -58,7 +76,19 @@ public function save()
5876
$this->article->addMedia($this->file->getRealPath())->toMediaCollection('media');
5977
}
6078

61-
$this->redirectRoute('articles.show', $this->article);
79+
if (! $this->alreadySubmitted) {
80+
// Envoi du mail a l'admin pour la validation de l'article
81+
$admin = User::findByEmailAddress('monneylobe@gmail.com');
82+
Notification::send($admin, new SendSubmittedArticle($this->article));
83+
84+
session()->flash('status', 'Merci d\'avoir soumis votre article. Vous aurez des nouvelles uniquement quand nous accepterons votre article.');
85+
}
86+
87+
Cache::forget('post-' . $this->article->id);
88+
89+
$user->hasRole('user') ?
90+
$this->redirectRoute('dashboard') :
91+
$this->redirectRoute('articles.show', $this->article);
6292
}
6393

6494
public function render()
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace App\Http\Livewire\Modals;
4+
5+
use App\Gamify\Points\PostCreated;
6+
use App\Models\Article;
7+
use App\Notifications\SendApprovedArticle;
8+
use App\Policies\ArticlePolicy;
9+
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
10+
use Illuminate\Support\Facades\Cache;
11+
use LivewireUI\Modal\ModalComponent;
12+
13+
class ApprovedArticle extends ModalComponent
14+
{
15+
use AuthorizesRequests;
16+
17+
public ?Article $article = null;
18+
19+
public function mount(int $id)
20+
{
21+
$this->article = Article::find($id);
22+
}
23+
24+
public static function modalMaxWidth(): string
25+
{
26+
return 'xl';
27+
}
28+
29+
public function approved()
30+
{
31+
$this->authorize(ArticlePolicy::UPDATE, $this->article);
32+
33+
$this->article->update(['approved_at' => now()]);
34+
35+
givePoint(new PostCreated($this->article));
36+
37+
Cache::forget('post-' . $this->article->id);
38+
39+
$this->article->author->notify(new SendApprovedArticle($this->article));
40+
41+
session()->flash('status', 'L\'article a été approuvé et le mail a été envoyé à l\'auteur pour le notifier.');
42+
43+
$this->redirectRoute('articles');
44+
}
45+
46+
public function render()
47+
{
48+
return view('livewire.modals.approved-article');
49+
}
50+
}

app/Http/Middleware/HttpsProtocol.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class HttpsProtocol
99
{
1010
public function handle(Request $request, Closure $next)
1111
{
12-
if (! $request->isSecure() && app()->environment('production')) {
12+
if (app()->environment('production') && ! $request->isSecure()) {
1313
return redirect()->secure($request->getRequestUri());
1414
}
1515

app/Models/Article.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class Article extends Model implements ReactableInterface, HasMedia, Viewable
7373
*/
7474
protected $with = [
7575
'author',
76+
'media',
7677
];
7778

7879
protected $removeViewsOnDelete = true;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace App\Notifications;
4+
5+
use App\Models\Article;
6+
use Illuminate\Bus\Queueable;
7+
use Illuminate\Notifications\Messages\MailMessage;
8+
use Illuminate\Notifications\Notification;
9+
10+
class SendApprovedArticle extends Notification
11+
{
12+
use Queueable;
13+
14+
public function __construct(public Article $article)
15+
{
16+
}
17+
18+
public function via($notifiable): array
19+
{
20+
return ['mail'];
21+
}
22+
23+
/**
24+
* Get the mail representation of the notification.
25+
*
26+
* @param mixed $notifiable
27+
* @return \Illuminate\Notifications\Messages\MailMessage
28+
*/
29+
public function toMail($notifiable)
30+
{
31+
return (new MailMessage)
32+
->subject('Article Approuvé 🎉.')
33+
->greeting('Article Approuvé 🎉.')
34+
->line('Merci d\'avoir soumis votre article pour créer du contenu au sein de Laravel Cameroun.')
35+
->action('Voir mon article', route('articles.show', $this->article))
36+
->line('Merci d\'avoir utilisé Laravel Cameroun.!');
37+
}
38+
}

app/Notifications/SendEMailToDeletedUser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ public function toMail($notifiable)
3535
->line('Pour des raisons de validité et d\'authenticité de votre adresse email')
3636
->line('Nous avons supprimé votre compte après 10 jours d\'inscription sans validation de votre adresse email.')
3737
->line('Nous ne pouvons donc pas authentifier que cette adresse email est belle et bien utilisée.')
38-
->line('Merci d\'avoir utilise Laravel Cameroun!');
38+
->line('Merci d\'avoir utilisé Laravel Cameroun!');
3939
}
4040
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace App\Notifications;
4+
5+
use App\Models\Article;
6+
use Illuminate\Bus\Queueable;
7+
use Illuminate\Notifications\Messages\MailMessage;
8+
use Illuminate\Notifications\Notification;
9+
10+
class SendSubmittedArticle extends Notification
11+
{
12+
use Queueable;
13+
14+
public function __construct(public Article $article)
15+
{
16+
}
17+
18+
public function via($notifiable): array
19+
{
20+
return ['mail'];
21+
}
22+
23+
/**
24+
* Get the mail representation of the notification.
25+
*
26+
* @param mixed $notifiable
27+
* @return \Illuminate\Notifications\Messages\MailMessage
28+
*/
29+
public function toMail($notifiable)
30+
{
31+
return (new MailMessage)
32+
->subject('Nouvelle soumission d\'article')
33+
->greeting('Bonjour Admin!')
34+
->line("Un nouvel article a été soumis par {$this->article->author->name}")
35+
->action('Afficher l\'article', route('articles.show', $this->article))
36+
->line('Merci d\'avoir utilisé Laravel Cameroun!');
37+
}
38+
}

app/Traits/HasProfilePhoto.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public function getProfilePhotoUrlAttribute(): string
1515
return $this->getFirstMediaUrl('avatar');
1616
}
1717

18-
$social_avatar = $this->providers()->where('provider', $this->avatar_type)->first();
18+
$social_avatar = $this->providers->where('provider', $this->avatar_type)->first();
1919

2020
if ($social_avatar && strlen($social_avatar->avatar)) {
2121
return $social_avatar->avatar;

app/Traits/WithArticleAttributes.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ trait WithArticleAttributes
1010
public ?string $slug = null;
1111
public string $body = '';
1212
public ?string $canonical_url = null;
13-
public bool $show_toc = true;
14-
public bool $submitted = true;
13+
public bool $show_toc = false;
1514
public ?string $submitted_at = null;
1615
public ?string $approved_at = null;
1716
public $file;
1817

1918
protected $rules = [
20-
'title' => ['required', 'max:150'],
21-
'body' => ['required'],
19+
'title' => 'required|max:150',
20+
'body' => 'required',
2221
'tags_selected' => 'nullable|array',
2322
'canonical_url' => 'nullable|url',
2423
'file' => 'nullable|image|max:2048', // 1MB Max

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
"lodash": "^4.17.19",
2222
"postcss": "^8.4.5",
2323
"postcss-loader": "^6.2.1",
24-
"postcss-preset-env": "^7.0.1",
25-
"prettier": "^2.3.1",
26-
"prettier-standard": "^16.4.1"
24+
"postcss-preset-env": "^7.0.1"
2725
},
2826
"dependencies": {
2927
"@alpinejs/intersect": "^3.6.1",

public/css/app.css

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/js/app.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/mix-manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"/js/app.js": "/js/app.js?id=c897f885ae4994f36dfc",
3-
"/css/app.css": "/css/app.css?id=84c90922f73faacd4564"
2+
"/js/app.js": "/js/app.js?id=1d8832a55a90910e91ad",
3+
"/css/app.css": "/css/app.css?id=543449437fc1da0337d7"
44
}

resources/views/articles/show.blade.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,18 @@ class="inline-flex items-center py-2 px-4 border border-skin-base rounded-md sha
211211
</div>
212212
<div class="relative flex justify-center">
213213
<span class="relative z-0 inline-flex shadow-sm rounded-md -space-x-px">
214-
<a href="{{ route('articles.edit', $article) }}" class="relative inline-flex items-center px-4 py-2 rounded-l-md border border-skin-base bg-skin-card text-sm font-medium text-gray-400 hover:bg-skin-card-muted focus:z-10 focus:outline-none focus:ring-1 focus:ring-green-500 focus:border-green-500 focus:ring-offset-body">
214+
<a href="{{ route('articles.edit', $article) }}" class="relative inline-flex items-center px-4 py-2 rounded-l-md border border-skin-base bg-skin-card text-sm font-medium text-skin-inverted-muted hover:bg-skin-card-muted focus:z-10 focus:outline-none focus:ring-1 focus:ring-green-500 focus:border-green-500 focus:ring-offset-body">
215215
<span class="sr-only">Éditer</span>
216216
<x-heroicon-s-pencil class="h-5 w-5" />
217217
</a>
218-
<button onclick="Livewire.emit('openModal', 'modals.delete-article', {{ json_encode([$article->id]) }})" type="button" class="relative inline-flex items-center px-4 py-2 rounded-r-md border border-skin-base bg-skin-card text-sm font-medium text-gray-400 hover:bg-skin-card-muted focus:z-10 focus:outline-none focus:ring-1 focus:ring-green-500 focus:border-green-500 focus:ring-offset-body">
218+
@if($article->isNotApproved())
219+
@hasanyrole('admin|moderator')
220+
<button onclick="Livewire.emit('openModal', 'modals.approved-article', {{ json_encode([$article->id]) }})" type="button" class="-ml-px relative inline-flex items-center px-4 py-2 border border-skin-base bg-skin-card text-sm font-medium text-green-500 hover:bg-skin-card-muted focus:z-10 focus:outline-none focus:ring-1 focus:ring-green-500 focus:border-green-500 focus:border-green-500 focus:ring-offset-body">
221+
<x-heroicon-s-badge-check class="h-5 w-5" />
222+
</button>
223+
@endhasanyrole
224+
@endif
225+
<button onclick="Livewire.emit('openModal', 'modals.delete-article', {{ json_encode([$article->id]) }})" type="button" class="relative inline-flex items-center px-4 py-2 rounded-r-md border border-skin-base bg-skin-card text-sm font-medium text-skin-inverted-muted hover:bg-skin-card-muted focus:z-10 focus:outline-none focus:ring-1 focus:ring-green-500 focus:border-green-500 focus:ring-offset-body">
219226
<span class="sr-only">Supprimer</span>
220227
<x-heroicon-s-trash class="h-5 w-5" />
221228
</button>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<button {{ $attributes->merge(['class' => 'inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-negative-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-negative-500 focus:outline-none focus:border-negative-700 sm:text-sm sm:leading-5 focus:ring-2 focus:ring-offset-2 focus:ring-offset-body focus:ring-negative-500']) }}>
2+
{{ $slot }}
3+
</button>

0 commit comments

Comments
 (0)