From f7cf59bf3c8180157a3cef64e8a250a03cbb9ea1 Mon Sep 17 00:00:00 2001 From: kyledoesdev Date: Wed, 16 Jul 2025 20:35:10 -0400 Subject: [PATCH 1/3] Prezet Updates - update prezet to not use zoomable and to handle images stored for a post in post slug convention sub dirs --- .../Controllers/Prezet/ImageController.php | 31 ++++- app/Livewire/Blog.php | 32 ++++- config/prezet.php | 2 +- resources/css/app.css | 126 ------------------ resources/views/livewire/blog.blade.php | 61 +++++++-- 5 files changed, 109 insertions(+), 143 deletions(-) diff --git a/app/Http/Controllers/Prezet/ImageController.php b/app/Http/Controllers/Prezet/ImageController.php index 39911c2..6a8d9fb 100644 --- a/app/Http/Controllers/Prezet/ImageController.php +++ b/app/Http/Controllers/Prezet/ImageController.php @@ -4,14 +4,17 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; +use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\Storage; use Prezet\Prezet\Prezet; +use Prezet\Prezet\Models\Document; class ImageController { public function __invoke(Request $request, string $path): Response { - $file = Prezet::getImage($path); - $size = strlen($file); + /* resolve img path from sub dir, trim off 'images/' & pass to prezet */ + $file = Prezet::getImage(ltrim($this->resolveImagePath($path), 'images/')); return response($file, 200, [ 'Content-Type' => match (pathinfo($path, PATHINFO_EXTENSION)) { @@ -19,9 +22,29 @@ public function __invoke(Request $request, string $path): Response 'png' => 'image/png', default => 'image/webp' }, - 'Content-Length' => $size, + 'Content-Length' => strlen($file), 'Accept-Ranges' => 'bytes', 'Cache-Control' => 'public, max-age=31536000', ]); } -} + + private function resolveImagePath(string $filename): ?string + { + /* remove any appended size version when looking up path */ + $originalFilename = preg_replace('/-\d+w\./', '.', $filename); + + $slugs = Document::pluck('slug')->toArray(); + + /* loop through the articles' slugs to get dir & file name from prezet disk */ + foreach ($slugs as $slug) { + $imagePath = "images/{$slug}/{$originalFilename}"; + + if (Storage::disk('prezet')->exists($imagePath)) { + return $imagePath; + } + } + + /* images should always be in their article's sub dir, so we should really never reach here. */ + return null; + } +} \ No newline at end of file diff --git a/app/Livewire/Blog.php b/app/Livewire/Blog.php index 8c70f1c..fbd8feb 100644 --- a/app/Livewire/Blog.php +++ b/app/Livewire/Blog.php @@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; use Livewire\Attributes\Computed; use Livewire\Attributes\Validate; use Livewire\Component; @@ -24,6 +25,9 @@ class Blog extends Component #[Validate('required|file|mimes:md')] public $file; + #[Validate(['images' => 'nullable|array', 'images.*' => 'image|max:4096'])] + public $images = []; + public function render() { return view('livewire.blog'); @@ -39,9 +43,26 @@ public function store() options: ['disk' => 'prezet'] ); + /* index in prezet disk */ Artisan::call('prezet:index'); + $document = Document::query()->latest()->first(); + + if ($document && $this->images) { + foreach ($this->images as $image) { + $image->storeAs( + path: "images/{$document->slug}", + name: $image->getClientOriginalName(), + options: ['disk' => 'prezet'] + ); + } + + /* index in prezet disk again (for the images) */ + Artisan::call('prezet:index'); + } + $this->file = null; + $this->images = []; Flux::toast(variant: 'success', text: 'Blog Post Uploaded!', duration: 3000); } @@ -53,11 +74,18 @@ public function destroy($id) if ($document) { try { /* delete the file */ - Storage::disk('prezet')->delete('content/'.$document->slug.'.md'); + Storage::disk('prezet')->delete("content/{$document->slug}.md"); /* delete the tags */ DB::connection('prezet')->table('document_tags')->where('document_id', $id)->delete(); + /* delete images if there are any */ + $imageDirectory = "images/{$document->slug}"; + + if (Storage::disk('prezet')->exists($imageDirectory)) { + Storage::disk('prezet')->deleteDirectory($imageDirectory); + } + /* delete the reference */ Document::where('id', $id)->delete(); @@ -90,4 +118,4 @@ public function posts() return $documents; } -} +} \ No newline at end of file diff --git a/config/prezet.php b/config/prezet.php index c56aca0..923d270 100644 --- a/config/prezet.php +++ b/config/prezet.php @@ -105,7 +105,7 @@ 'sizes' => '92vw, (max-width: 1024px) 92vw, 768px', - 'zoomable' => true, + 'zoomable' => false, ], /* diff --git a/resources/css/app.css b/resources/css/app.css index fa7e11f..4a1201a 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -156,132 +156,6 @@ white-space: nowrap; width: 1px; } - - /* - |-------------------------------------------------------------------------- - | Alpinejs Zoomable - |-------------------------------------------------------------------------- - | https://github.com/benbjurstrom/alpinejs-zoomable - | - */ - - img[x-zoomable]:hover { - cursor: zoom-in; - } - - .zoomable-fullscreen-container { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100vh; - background: rgba(255, 255, 255, 0.9); - display: none; - z-index: 998; - cursor: zoom-out; - overflow: hidden; - touch-action: none; - } - - .zoomable-fullscreen-image { - position: absolute; - max-height: none; - max-width: none; - cursor: grab; - transition: transform 0.2s ease-out; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - touch-action: none; - -webkit-user-select: none; - user-select: none; - } - - .zoomable-fullscreen-image.dragging { - cursor: grabbing; - transition: none; - } - - .zoomable-controls-panel { - position: fixed; - top: 20px; - right: 20px; - display: flex; - gap: 10px; - z-index: 999; - } - - .zoomable-control-button { - background: #a1a1aa; - border: none; - color: white; - width: 40px; - height: 40px; - border-radius: 50%; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - transition: background-color 0.2s; - } - - .zoomable-control-button > svg { - width: 20px; - height: 20px; - } - - .zoomable-control-button:hover, - .zoomable-control-button:focus { - background: #71717a; - outline: none; - } - - @media (max-width: 768px) { - .zoomable-controls-panel { - top: 10px; - right: 10px; - } - - .zoomable-control-button { - width: 44px; - height: 44px; - -webkit-tap-highlight-color: transparent; /* Prevents gray flash on iOS */ - touch-action: manipulation; /* Optimize for touch */ - } - } - - .zoomable-loading-indicator { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 1000; - display: flex; - flex-direction: column; - align-items: center; - color: #737373; - font-size: 1rem; - } - - .zoomable-spinner { - width: 40px; - height: 40px; - border: 4px solid rgba(255, 255, 255, 0.3); - border-top: 4px solid #737373; - border-radius: 50%; - animation: spin 1s linear infinite; - margin-bottom: 10px; - } - - @keyframes spin { - to { - transform: rotate(360deg); - } - } - - .zoomable-loading-indicator[hidden] { - display: none; - } } @theme { diff --git a/resources/views/livewire/blog.blade.php b/resources/views/livewire/blog.blade.php index 96e4e37..d94c722 100644 --- a/resources/views/livewire/blog.blade.php +++ b/resources/views/livewire/blog.blade.php @@ -2,19 +2,60 @@ Blog Posts -
-
- +
+
+
+ + + +
-
- -
- Upload + + @if ($images) +
+ + {{ count($images) }} image(s) selected + +
+ @endif + +
+ + Upload Blog Post + + + @if ($file || $images) + + Clear + + @endif +
+ + @error('file') + {{ $message }} + @enderror + + @error('images.*') + {{ $message }} + @enderror
- + -
+
@forelse ($this->posts as $post) @@ -82,6 +123,6 @@ @endforelse
-
+
\ No newline at end of file From c274b8c0fea098463bd6406b9f4c85da7cb5500f Mon Sep 17 00:00:00 2001 From: kyledoesdev Date: Wed, 16 Jul 2025 20:45:47 -0400 Subject: [PATCH 2/3] small changes --- app/Livewire/Blog.php | 7 ++ resources/views/livewire/blog.blade.php | 99 +++++++++++++------------ 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/app/Livewire/Blog.php b/app/Livewire/Blog.php index fbd8feb..7e35d3e 100644 --- a/app/Livewire/Blog.php +++ b/app/Livewire/Blog.php @@ -118,4 +118,11 @@ public function posts() return $documents; } + + public function clearUploads() + { + $this->file = null; + $this->images = []; + $this->resetValidation(); + } } \ No newline at end of file diff --git a/resources/views/livewire/blog.blade.php b/resources/views/livewire/blog.blade.php index d94c722..b43e61a 100644 --- a/resources/views/livewire/blog.blade.php +++ b/resources/views/livewire/blog.blade.php @@ -1,59 +1,60 @@
Blog Posts - -
-
-
- - - -
-
- - @if ($images) -
- - {{ count($images) }} image(s) selected - + + +
+
+
+ + + +
- @endif - -
- - Upload Blog Post - - @if ($file || $images) - - Clear - + @if ($images) +
+ + {{ count($images) }} image(s) selected + +
@endif -
- - @error('file') - {{ $message }} - @enderror - - @error('images.*') - {{ $message }} - @enderror -
+ +
+ + Upload Blog Post + + + @if ($file || $images) + + Clear + + @endif +
- + @error('file') + {{ $message }} + @enderror + + @error('images.*') + {{ $message }} + @enderror +
+
From 1937108075a44fd3812fa5ee20cbea31560d2e42 Mon Sep 17 00:00:00 2001 From: kyledoesdev Date: Wed, 16 Jul 2025 21:04:33 -0400 Subject: [PATCH 3/3] pint --- app/Http/Controllers/AssetController.php | 2 +- app/Http/Controllers/Prezet/ImageController.php | 11 +++++------ app/Livewire/Blog.php | 7 +++---- app/Livewire/Forms/PhotoForm.php | 4 ++-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/AssetController.php b/app/Http/Controllers/AssetController.php index ed72475..7a3aa2e 100644 --- a/app/Http/Controllers/AssetController.php +++ b/app/Http/Controllers/AssetController.php @@ -12,7 +12,7 @@ public function __invoke(Request $request, string $slug) { return Storage::disk('s3') ->response(Asset::where('slug', $slug)->firstOrFail()->path, null, [ - 'Cache-Control' => 'public, max-age=31536000' + 'Cache-Control' => 'public, max-age=31536000', ]); } } diff --git a/app/Http/Controllers/Prezet/ImageController.php b/app/Http/Controllers/Prezet/ImageController.php index 6a8d9fb..f836f9e 100644 --- a/app/Http/Controllers/Prezet/ImageController.php +++ b/app/Http/Controllers/Prezet/ImageController.php @@ -4,10 +4,9 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; -use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Storage; -use Prezet\Prezet\Prezet; use Prezet\Prezet\Models\Document; +use Prezet\Prezet\Prezet; class ImageController { @@ -32,13 +31,13 @@ private function resolveImagePath(string $filename): ?string { /* remove any appended size version when looking up path */ $originalFilename = preg_replace('/-\d+w\./', '.', $filename); - + $slugs = Document::pluck('slug')->toArray(); - + /* loop through the articles' slugs to get dir & file name from prezet disk */ foreach ($slugs as $slug) { $imagePath = "images/{$slug}/{$originalFilename}"; - + if (Storage::disk('prezet')->exists($imagePath)) { return $imagePath; } @@ -47,4 +46,4 @@ private function resolveImagePath(string $filename): ?string /* images should always be in their article's sub dir, so we should really never reach here. */ return null; } -} \ No newline at end of file +} diff --git a/app/Livewire/Blog.php b/app/Livewire/Blog.php index 7e35d3e..0e089c2 100644 --- a/app/Livewire/Blog.php +++ b/app/Livewire/Blog.php @@ -8,7 +8,6 @@ use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; -use Illuminate\Support\Str; use Livewire\Attributes\Computed; use Livewire\Attributes\Validate; use Livewire\Component; @@ -48,7 +47,7 @@ public function store() $document = Document::query()->latest()->first(); - if ($document && $this->images) { + if ($document && $this->images) { foreach ($this->images as $image) { $image->storeAs( path: "images/{$document->slug}", @@ -81,7 +80,7 @@ public function destroy($id) /* delete images if there are any */ $imageDirectory = "images/{$document->slug}"; - + if (Storage::disk('prezet')->exists($imageDirectory)) { Storage::disk('prezet')->deleteDirectory($imageDirectory); } @@ -125,4 +124,4 @@ public function clearUploads() $this->images = []; $this->resetValidation(); } -} \ No newline at end of file +} diff --git a/app/Livewire/Forms/PhotoForm.php b/app/Livewire/Forms/PhotoForm.php index b0a2ecd..dc14d0b 100644 --- a/app/Livewire/Forms/PhotoForm.php +++ b/app/Livewire/Forms/PhotoForm.php @@ -90,9 +90,9 @@ private function getStorageDisk(): string private function processImage(): void { - $manager = new ImageManager(new Driver()); + $manager = new ImageManager(new Driver); $image = $manager->read($this->photo->getRealPath()); - + if ($image->width() > 2000 || $image->height() > 1500) { $image->scaleDown(width: 2000, height: 1500); $image->save($this->photo->getRealPath());