Skip to content

Commit

Permalink
Merge pull request #188 from alimranahmed/187-cosmetic-changes-in-adm…
Browse files Browse the repository at this point in the history
…in-panel

187 cosmetic changes in admin panel
  • Loading branch information
alimranahmed authored Sep 13, 2024
2 parents 81fd123 + ceb8bb9 commit 97bce74
Show file tree
Hide file tree
Showing 16 changed files with 333 additions and 62 deletions.
18 changes: 18 additions & 0 deletions app/Http/Controllers/FileController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace App\Http\Controllers;

use App\Models\Image;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

class FileController extends Controller
{
public function path($uuid): BinaryFileResponse
{
/** @var ?Image $image */
$image = Image::query()->where('uuid', $uuid)->firstOrFail();

return response()->download(Storage::path($image->src));
}
}
82 changes: 50 additions & 32 deletions app/Livewire/Backend/Article/Form.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<?php
declare(strict_types=1);

namespace App\Livewire\Backend\Article;

use League\CommonMark\Exception\CommonMarkException;
use App\Mail\NotifySubscriberForNewArticle;
use App\Models\Article;
use App\Models\Category;
Expand All @@ -16,10 +18,12 @@

class Form extends Component
{
public Article $originalArticle;
public ?Article $article = null;

public array $articleData = [];

public string $contentPreview = '';

public string $method;

public array $rules = [
Expand All @@ -33,33 +37,26 @@ class Form extends Component
'articleData.meta.image_url' => 'nullable|url',
];

public function mount($article = null): void
/**
* @throws CommonMarkException
*/
public function mount(): void
{
if ($article?->id) {
if ($this->article) {
/** @var User $user */
$user = Auth::user();
if (! $article->hasAuthorization($user)) {
if (! $this->article->hasAuthorization($user)) {
$this->redirectRoute('home');
return;
}

$this->originalArticle = $article;
$this->articleData = $article->toArray();
$this->articleData['keywords'] = $article->keywords->pluck('name')->implode(' ');
$this->articleData['meta'] = $article->meta ?: [];
$this->articleData = $this->article->toArray();
$this->articleData['keywords'] = $this->article->keywords->pluck('name')->implode(' ');
$this->articleData['meta'] = $this->article->meta ?: [];
$this->contentPreview = Article::markdownToHtml($this->article->content);
}

$this->method = $article?->id ? 'put' : 'post';
}

public function render(): View
{
if (Arr::get($this->articleData, 'heading')) {
$this->articleData['slug'] = Str::slug(Arr::get($this->articleData, 'heading'), '-', Arr::get($this->articleData, 'language'));
}
$categories = Category::query()->active()->get();

return view('livewire.backend.article.form', compact('categories'));
$this->method = $this->article === null ? 'post' : 'put';
}

public function submit(): void
Expand All @@ -85,9 +82,6 @@ protected function store(array $articleData): void
$keywordsToAttach = $this->getKeywords();

foreach ($keywordsToAttach as $keywordToAttach) {
if (empty($keywordToAttach)) {
continue;
}
/** @var Keyword $newKeyword */
$newKeyword = Keyword::query()->firstOrCreate(['name' => $keywordToAttach]);
$newArticle->keywords()->attach($newKeyword->id);
Expand All @@ -99,28 +93,52 @@ protected function store(array $articleData): void
}

session()->flash('success', 'Article published successfully!');
redirect()->to(route('backend.article.index'));
}

public function getKeywords(): array {
return array_filter(array_unique(explode(' ', Arr::get($this->articleData, 'keywords'))));
$this->redirectRoute('backend.article.index', navigate: true);
}

protected function update(array $updateData): void
{
$this->originalArticle->update($updateData);
$this->article->update($updateData);

$this->originalArticle->keywords()->detach();
$this->article->keywords()->detach();

$keywordsToAttach = array_unique(explode(' ', Arr::get($this->articleData, 'keywords')));
$keywordsToAttach = $this->getKeywords();

foreach ($keywordsToAttach as $keywordToAttach) {
/** @var Keyword $newKeyword */
$newKeyword = Keyword::query()->firstOrCreate(['name' => $keywordToAttach]);
$this->originalArticle->keywords()->attach($newKeyword->id);
$this->article->keywords()->attach($newKeyword->id);
}

session()->flash('successMsg', 'Article updated successfully!');
redirect()->to(route('backend.article.index'));
$this->redirectRoute('backend.article.index', navigate: true);
}

public function getKeywords(): array {
return array_filter(
array_unique(
explode(' ', Arr::get($this->articleData, 'keywords', ''))
)
);
}

/**
* @throws CommonMarkException
*/
public function updated(string $property): void {
if ($property === 'articleData.content') {
$this->contentPreview = Article::markdownToHtml($this->articleData['content']);
}
}

public function render(): View
{
if (Arr::get($this->articleData, 'heading')) {
$this->articleData['slug'] = Str::slug(Arr::get($this->articleData, 'heading'), '-', Arr::get($this->articleData, 'language'));
}

$categories = Category::query()->active()->get();

return view('livewire.backend.article.form', compact('categories'));
}
}
65 changes: 65 additions & 0 deletions app/Livewire/Backend/Article/ImageForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);

namespace App\Livewire\Backend\Article;

use App\Models\Image;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Str;
use Livewire\Attributes\Validate;
use Livewire\Component;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Livewire\WithFileUploads;

class ImageForm extends Component
{
use WithFileUploads;

#[Validate(['image' => 'image|max:2048'])] // 2MB
public null|TemporaryUploadedFile $image = null;

public array $files = [];

public function render(): View
{
return view('livewire.backend.article.image-form');
}

public function updatedImage(): void
{
$this->validate();
$this->save();
}

public function save(): void
{
$path = $this->image->store(path: 'images');

/** @var Image $image */
$image = Image::query()->create([
'uuid' => Str::uuid(),
'src' => $path,
'src_type' => 'internal',
]);

$this->files[] = [
'name' => $this->image->getClientOriginalName(),
'url' => route('file', [$image->uuid]),
'size' => $this->formatFileSize($this->image->getSize()),
];
}

private function formatFileSize(int $bytes, int $precision = 2): string
{
$units = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];

if ($bytes == 0) {
return '0 Bytes';
}

$index = floor(log($bytes, 1024)); // Find the appropriate unit
$fileSize = $bytes / pow(1024, $index); // Convert size to the appropriate unit

return round($fileSize, $precision) . ' ' . $units[$index];
}
}
17 changes: 13 additions & 4 deletions app/Models/Article.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use League\CommonMark\MarkdownConverter;
use Tempest\Highlight\CommonMark\HighlightExtension;
use Tempest\Highlight\Highlighter;
use League\CommonMark\Exception\CommonMarkException;

/**
* @property Category $category
Expand Down Expand Up @@ -79,6 +80,16 @@ public function categoryName(): Attribute
}

public function htmlContent(): Attribute
{
return Attribute::make(
get: fn () => self::markdownToHtml($this->content)
);
}

/**
* @throws CommonMarkException
*/
public static function markdownToHtml(string $markdownContent): string
{
$environment = new Environment();

Expand All @@ -88,11 +99,9 @@ public function htmlContent(): Attribute
->addExtension(new CommonMarkCoreExtension())
->addExtension(new HighlightExtension($highlighter));

$markdown = new MarkdownConverter($environment);
$markdownConverter = new MarkdownConverter($environment);

return Attribute::make(
get: fn () => $markdown->convert($this->content)
);
return $markdownConverter->convert($markdownContent);
}

public function hasAuthorization(User $user): bool
Expand Down
4 changes: 4 additions & 0 deletions app/Models/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

use Illuminate\Database\Eloquent\Model;

/**
* @property string $uuid
* @property string $src
*/
class Image extends Model
{
protected $guarded = ['id'];
Expand Down
28 changes: 28 additions & 0 deletions database/migrations/2024_09_12_230821_add_uuid_in_images_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('images', function (Blueprint $table) {
$table->uuid()->after('id');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('images', function (Blueprint $table) {
$table->dropColumn('uuid');
});
}
};
1 change: 0 additions & 1 deletion public/build/assets/app-B5VvTx68.css

This file was deleted.

1 change: 1 addition & 0 deletions public/build/assets/app-fd8BV2NW.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/build/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"resources/css/app.css": {
"file": "assets/app-B5VvTx68.css",
"file": "assets/app-fd8BV2NW.css",
"src": "resources/css/app.css",
"isEntry": true
},
Expand Down
2 changes: 1 addition & 1 deletion resources/views/components/backend/form/input.blade.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@props(['type' => 'text', 'name'])
<input type="{{$type}}" name="{{$name}}"
{{$attributes->merge(['class' => 'p-1 border border-indigo-300 rounded focus:outline-none focus:border-indigo-500'])}}
{{$attributes->merge(['class' => 'p-1 border border-indigo-300 rounded focus:outline-none focus:ring-0 focus:border-indigo-500'])}}
>

@error($name)
Expand Down
4 changes: 2 additions & 2 deletions resources/views/components/backend/form/select.blade.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@props(['name'])

<select name="{{$name}}"
{{$attributes->merge(['class' => 'block p-1 border border-indigo-300 rounded focus:outline-none focus:border-indigo-500'])}}
<select name="{{$name}}"
{{$attributes->merge(['class' => 'block p-1 border border-indigo-300 rounded focus:outline-none focus:ring-0 focus:border-indigo-500'])}}
>
{{$slot}}
</select>
9 changes: 7 additions & 2 deletions resources/views/components/backend/form/textarea.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
@props(['type' => 'text', 'name'])
@props(['type' => 'text', 'name', 'rounded' => true])

@php
$class = $rounded ? 'rounded' : '';
@endphp

<textarea type="{{$type}}" name="{{$name}}"
{{$attributes->merge(['class' => 'p-1 border border-indigo-300 rounded focus:outline-none focus:border-indigo-500'])}}
{{$attributes->merge(['class' => "p-1 border border-indigo-300 focus:outline-none focus:ring-0 focus:border-indigo-500 $class"])}}
>{{$slot}}</textarea>
2 changes: 2 additions & 0 deletions resources/views/components/layouts/backend.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

<title>{{$globalConfigs->site_title}}</title>

@stack('styles')
</head>
<body>

Expand All @@ -21,5 +22,6 @@
{{$slot}}
</div>

@stack('scripts')
</body>
</html>
Loading

0 comments on commit 97bce74

Please sign in to comment.