diff --git a/config/curator.php b/config/curator.php index 9cbf5c2c..b31174cf 100644 --- a/config/curator.php +++ b/config/curator.php @@ -23,7 +23,7 @@ 'curation_presets' => [ \Awcodes\Curator\Curations\ThumbnailPreset::class, ], - 'directory' => 'media', + 'directory' => null, 'disk' => env('FILAMENT_FILESYSTEM_DISK', 'public'), 'glide' => [ 'server' => \Awcodes\Curator\Glide\DefaultServerFactory::class, diff --git a/database/factories/MediaFactory.php b/database/factories/MediaFactory.php index 53b25985..0ba653a0 100644 --- a/database/factories/MediaFactory.php +++ b/database/factories/MediaFactory.php @@ -5,15 +5,90 @@ use Awcodes\Curator\Models\Media; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Str; use Intervention\Image\Facades\Image; +use \Illuminate\Http\UploadedFile; class MediaFactory extends Factory { protected $model = Media::class; + protected ?string $directory = null; + + protected ?string $disk = null; + + protected ?string $type = null; + public function definition(): array { - $fileName = collect([ + return match ($this->getType()) { + 'svg' => $this->handleSvg(), + 'pdf' => $this->handlePdf(), + 'video' => $this->handleVideo(), + default => $this->handleJpg(), + }; + } + + public function private(): MediaFactory + { + return $this->state(function (array $attributes) { + return [ + 'visibility' => 'private', + ]; + }); + } + + public function randomTimestamps(): MediaFactory + { + return $this->state(function (array $attributes) { + return [ + 'created_at' => \Carbon\Carbon::now()->addDays(rand(-800, 0))->addMinutes(rand(0, + 60 * 23))->addSeconds(rand(0, 60)), + 'updated_at' => \Carbon\Carbon::now()->addDays(rand(-799, 0))->addMinutes(rand(0, + 60 * 23))->addSeconds(rand(0, 60)) + ]; + }); + } + + public function directory(string $directory): static + { + $this->directory = $directory; + + return $this; + } + + public function disk(string $disk): static + { + $this->disk = $disk; + + return $this; + } + + public function type(string $type): static + { + $this->type = $type; + + return $this; + } + + public function getDirectory(): ?string + { + return $this->directory ?? config('curator.directory'); + } + + public function getDisk(): ?string + { + return $this->disk ?? config('curator.disk'); + } + + public function getType(): string + { + return $this->type ?? 'jpg'; + } + + public function handleJpg(): array + { + $filename = collect([ 'alberto-restifo-Ni4NgA64TFQ-unsplash', 'blake-verdoorn-cssvEZacHvQ-unsplash', 'daniel-roe-lpjb_UMOyx8-unsplash', @@ -38,19 +113,19 @@ public function definition(): array 'tim-swaan-eOpewngf68w-unsplash', ])->random() . '.jpg'; - $directory = config('curator.directory'); - $disk = config('curator.disk'); + $disk = $this->getDisk(); + $directory = $this->getDirectory(); - if (!Storage::disk($disk)->exists($directory . '/' . $fileName)) { - $fileContents = file_get_contents('https://res.cloudinary.com/aw-codes/image/upload/curator/seed-data/' . $fileName); - Storage::disk($disk)->put($directory . '/' . $fileName, $fileContents); + if (!Storage::disk($disk)->exists($directory . '/' . $filename)) { + $fileContents = file_get_contents('https://res.cloudinary.com/aw-codes/image/upload/curator/seed-data/' . $filename); + Storage::disk($disk)->put($directory . '/' . $filename, $fileContents); } - $data = Image::make(Storage::disk($disk)->path($directory . '/' . $fileName)); + $data = Image::make(Storage::disk($disk)->path($directory . '/' . $filename)); return [ 'name' => $data->filename, - 'path' => $directory . '/' . $fileName, + 'path' => $directory ? $directory . '/' . $filename : $filename, 'ext' => $data->extension, 'type' => $data->mime(), 'alt' => $this->faker->words(rand(3, 8), true), @@ -66,24 +141,98 @@ public function definition(): array ]; } - public function private(): MediaFactory + public function handleSvg(): array { - return $this->state(function (array $attributes) { - return [ - 'visibility' => 'private', - ]; - }); + $filename = collect([ + 'awcodes-logo', + 'search', + 'screen', + 'brand', + 'apps', + 'link', + ])->random() . '.svg'; + + $disk = $this->getDisk(); + $directory = $this->getDirectory(); + + if (!Storage::disk($disk)->exists($directory . '/' . $filename)) { + $fileContents = file_get_contents('https://res.cloudinary.com/aw-codes/image/upload/curator/seed-data/' . $filename); + Storage::disk($disk)->put($directory . '/' . $filename, $fileContents); + } + + return [ + 'name' => Str::of($filename)->before('.svg')->toString(), + 'path' => $directory ? $directory . '/' . $filename : $filename, + 'ext' => 'svg', + 'type' => Storage::disk($disk)->mimeType($directory . '/' . $filename), + 'alt' => $this->faker->words(rand(3, 8), true), + 'title' => null, + 'caption' => null, + 'description' => null, + 'width' => null, + 'height' => null, + 'disk' => $disk, + 'directory' => $directory, + 'size' => Storage::disk($disk)->size($directory . '/' . $filename) ?? null, + 'visibility' => 'public', + ]; } - public function randomTimestamps(): MediaFactory + public function handlePdf(): array { - return $this->state(function (array $attributes) { - return [ - 'created_at' => \Carbon\Carbon::now()->addDays(rand(-800, 0))->addMinutes(rand(0, - 60 * 23))->addSeconds(rand(0, 60)), - 'updated_at' => \Carbon\Carbon::now()->addDays(rand(-799, 0))->addMinutes(rand(0, - 60 * 23))->addSeconds(rand(0, 60)) - ]; - }); + $filename = Str::uuid() . '.pdf'; + $filesize = mt_rand(1000, 2000); + $disk = $this->getDisk(); + $directory = $this->getDirectory(); + + UploadedFile::fake()->create($filename, $filesize, 'application/pdf')->storeAs($directory . '/' . $filename, [ + 'disk' => $disk, + ]); + + return [ + 'name' => Str::of($filename)->before('.pdf')->toString(), + 'path' => $directory ? $directory . '/' . $filename : $filename, + 'ext' => 'pdf', + 'type' => 'application/pdf', + 'alt' => $this->faker->words(rand(3, 8), true), + 'title' => null, + 'caption' => null, + 'description' => null, + 'width' => null, + 'height' => null, + 'disk' => $disk, + 'directory' => $directory, + 'size' => $filesize, + 'visibility' => 'public', + ]; + } + + public function handleVideo(): array + { + $filename = Str::uuid() . '.mp4'; + $filesize = mt_rand(1000, 2000); + $disk = $this->getDisk(); + $directory = $this->getDirectory(); + + UploadedFile::fake()->create($filename, $filesize, 'video/mp4')->storeAs($directory . '/' . $filename, [ + 'disk' => $disk, + ]); + + return [ + 'name' => Str::of($filename)->before('.pdf')->toString(), + 'path' => $directory ? $directory . '/' . $filename : $filename, + 'ext' => 'mp4', + 'type' => 'video/mp4', + 'alt' => $this->faker->words(rand(3, 8), true), + 'title' => null, + 'caption' => null, + 'description' => null, + 'width' => null, + 'height' => null, + 'disk' => $disk, + 'directory' => $directory, + 'size' => $filesize, + 'visibility' => 'public', + ]; } } diff --git a/database/migrations/create_media_table.php.stub b/database/migrations/create_media_table.php.stub index 9c75cff0..dd41298d 100644 --- a/database/migrations/create_media_table.php.stub +++ b/database/migrations/create_media_table.php.stub @@ -12,7 +12,7 @@ return new class extends Migration Schema::create(app(config('curator.model'))->getTable(), function (Blueprint $table) { $table->id(); $table->string('disk')->default('public'); - $table->string('directory')->default('media'); + $table->string('directory')->nullable(); $table->string('visibility')->default('public'); $table->string('name'); $table->string('path'); diff --git a/database/migrations/upgrade_media_table.php.stub b/database/migrations/upgrade_media_table.php.stub deleted file mode 100644 index 183503ba..00000000 --- a/database/migrations/upgrade_media_table.php.stub +++ /dev/null @@ -1,23 +0,0 @@ -getTable(), function (Blueprint $table) { - $table->string('visibility')->default('public')->after('disk'); - }); - } - - public function down(): void - { - Schema::table(app(config('curator.model'))->getTable(), function(Blueprint $table) { - $table->dropColumn(['visibility']); - }); - } -}; diff --git a/resources/css/plugin.css b/resources/css/plugin.css index 7bbe2bba..313f278c 100644 --- a/resources/css/plugin.css +++ b/resources/css/plugin.css @@ -69,6 +69,14 @@ } } +.curator-picker-grid { + @apply grid grid-cols-3 gap-4 sm:grid-cols-4 md:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10; +} + +.filepond--panel { + @apply bg-transparent border-dashed border-2 border-gray-950/5 dark:border-white/20; +} + [wire\:key*="open_curator_picker"], [wire\:key*="open_curation_panel"], .curator-panel { @@ -99,13 +107,5 @@ > .fi-modal-footer { @apply pb-0; } - - .curator-picker-grid { - @apply grid grid-cols-3 gap-4 sm:grid-cols-4 md:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-10; - } - - .filepond--panel { - @apply bg-transparent border-dashed border-2 border-gray-950/5 dark:border-white/20; - } } } diff --git a/resources/dist/curator.css b/resources/dist/curator.css index 35347268..a335d825 100644 --- a/resources/dist/curator.css +++ b/resources/dist/curator.css @@ -1 +1 @@ -.curator-grid-container{--grid-layout-gap:1.5rem;--grid-column-count:1;--grid-item--min-width:75px;--gap-count:calc(var(--grid-column-count) - 1);--total-gap-width:calc(var(--gap-count)*var(--grid-layout-gap));--grid-item--max-width:calc((100% - var(--total-gap-width))/var(--grid-column-count));display:grid;grid-template-columns:repeat(auto-fill,minmax(max(var(--grid-item--min-width),var(--grid-item--max-width)),1fr));grid-gap:var(--grid-layout-gap)}@media (min-width:768px){.curator-grid-container{--grid-column-count:2}}@media (min-width:1024px){.curator-grid-container{--grid-column-count:3}}.checkered{background-color:rgba(var(--gray-200),1);background-image:repeating-linear-gradient(45deg,rgba(var(--gray-300),1) 25%,#0000 25%,#0000 75%,rgba(var(--gray-300),1) 75%,rgba(var(--gray-300),1)),repeating-linear-gradient(45deg,rgba(var(--gray-300),1) 25%,rgba(var(--gray-200),1) 25%,rgba(var(--gray-200),1) 75%,rgba(var(--gray-300),1) 75%,rgba(var(--gray-300),1));background-position:0 0,10px 10px;background-size:20px 20px}.dark .checkered{background-color:rgba(var(--gray-800),1);background-image:repeating-linear-gradient(45deg,rgba(var(--gray-700),1) 25%,#0000 25%,#0000 75%,rgba(var(--gray-700),1) 75%,rgba(var(--gray-700),1)),repeating-linear-gradient(45deg,rgba(var(--gray-700),1) 25%,rgba(var(--gray-800),1) 25%,rgba(var(--gray-800),1) 75%,rgba(var(--gray-700),1) 75%,rgba(var(--gray-700),1))}.fi-resources-media .fi-forms-tabs-component-header{--tw-bg-opacity:1;background-color:rgba(var(--gray-100),var(--tw-bg-opacity))}:is(.dark .fi-resources-media .fi-forms-tabs-component-header){--tw-bg-opacity:1;background-color:rgba(var(--gray-900),var(--tw-bg-opacity))}.fi-resources-media .fi-tables-component .fi-tables-record-checkbox{z-index:1}.curator-panel-sidebar .fi-fo-component-ctn{gap:1rem}.curator-panel-sidebar .fi-fo-component-ctn label{font-size:.875rem;line-height:1.25rem}.curator-panel-sidebar .filepond--root{min-height:300px}.curator-panel>.fi-modal-window,[wire\:key*=open_curation_panel]>.fi-modal-window,[wire\:key*=open_curator_picker]>.fi-modal-window{padding:0!important}.curator-panel>.fi-modal-window>.fi-modal-header,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgba(var(--gray-300),var(--tw-border-opacity));padding:.5rem 1rem}:is(.dark .curator-panel>.fi-modal-window>.fi-modal-header),:is(.dark [wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header),:is(.dark [wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header){--tw-border-opacity:1;border-color:rgba(var(--gray-800),var(--tw-border-opacity))}.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-heading,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-heading,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-heading{font-size:1rem;line-height:1.5rem}.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-close-btn,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn{margin-block-start:-.75rem}.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:focus,.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:hover,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:focus,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:hover,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:focus,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:hover{background-color:initial!important;--tw-text-opacity:1;color:rgba(var(--primary-500),var(--tw-text-opacity))}.curator-panel>.fi-modal-window>.fi-modal-content,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-content,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-content{position:relative}.curator-panel>.fi-modal-window>.fi-modal-footer,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-footer,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-footer{padding-bottom:0}.curator-panel>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curation_panel]>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curator_picker]>.fi-modal-window .curator-picker-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem}@media (min-width:640px){.curator-panel>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curation_panel]>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curator_picker]>.fi-modal-window .curator-picker-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:768px){.curator-panel>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curation_panel]>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curator_picker]>.fi-modal-window .curator-picker-grid{grid-template-columns:repeat(6,minmax(0,1fr))}}@media (min-width:1280px){.curator-panel>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curation_panel]>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curator_picker]>.fi-modal-window .curator-picker-grid{grid-template-columns:repeat(8,minmax(0,1fr))}}@media (min-width:1536px){.curator-panel>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curation_panel]>.fi-modal-window .curator-picker-grid,[wire\:key*=open_curator_picker]>.fi-modal-window .curator-picker-grid{grid-template-columns:repeat(10,minmax(0,1fr))}}.curator-panel>.fi-modal-window .filepond--panel,[wire\:key*=open_curation_panel]>.fi-modal-window .filepond--panel,[wire\:key*=open_curator_picker]>.fi-modal-window .filepond--panel{border-width:2px;border-style:dashed;border-color:rgba(var(--gray-950),.05);background-color:initial}:is(.dark .curator-panel>.fi-modal-window .filepond--panel),:is(.dark [wire\:key*=open_curation_panel]>.fi-modal-window .filepond--panel),:is(.dark [wire\:key*=open_curator_picker]>.fi-modal-window .filepond--panel){border-color:#fff3} \ No newline at end of file +.curator-grid-container{--grid-layout-gap:1.5rem;--grid-column-count:1;--grid-item--min-width:75px;--gap-count:calc(var(--grid-column-count) - 1);--total-gap-width:calc(var(--gap-count)*var(--grid-layout-gap));--grid-item--max-width:calc((100% - var(--total-gap-width))/var(--grid-column-count));display:grid;grid-template-columns:repeat(auto-fill,minmax(max(var(--grid-item--min-width),var(--grid-item--max-width)),1fr));grid-gap:var(--grid-layout-gap)}@media (min-width:768px){.curator-grid-container{--grid-column-count:2}}@media (min-width:1024px){.curator-grid-container{--grid-column-count:3}}.checkered{background-color:rgba(var(--gray-200),1);background-image:repeating-linear-gradient(45deg,rgba(var(--gray-300),1) 25%,#0000 25%,#0000 75%,rgba(var(--gray-300),1) 75%,rgba(var(--gray-300),1)),repeating-linear-gradient(45deg,rgba(var(--gray-300),1) 25%,rgba(var(--gray-200),1) 25%,rgba(var(--gray-200),1) 75%,rgba(var(--gray-300),1) 75%,rgba(var(--gray-300),1));background-position:0 0,10px 10px;background-size:20px 20px}.dark .checkered{background-color:rgba(var(--gray-800),1);background-image:repeating-linear-gradient(45deg,rgba(var(--gray-700),1) 25%,#0000 25%,#0000 75%,rgba(var(--gray-700),1) 75%,rgba(var(--gray-700),1)),repeating-linear-gradient(45deg,rgba(var(--gray-700),1) 25%,rgba(var(--gray-800),1) 25%,rgba(var(--gray-800),1) 75%,rgba(var(--gray-700),1) 75%,rgba(var(--gray-700),1))}.fi-resources-media .fi-forms-tabs-component-header{--tw-bg-opacity:1;background-color:rgba(var(--gray-100),var(--tw-bg-opacity))}:is(.dark .fi-resources-media .fi-forms-tabs-component-header){--tw-bg-opacity:1;background-color:rgba(var(--gray-900),var(--tw-bg-opacity))}.fi-resources-media .fi-tables-component .fi-tables-record-checkbox{z-index:1}.curator-panel-sidebar .fi-fo-component-ctn{gap:1rem}.curator-panel-sidebar .fi-fo-component-ctn label{font-size:.875rem;line-height:1.25rem}.curator-panel-sidebar .filepond--root{min-height:300px}.curator-picker-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem}@media (min-width:640px){.curator-picker-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:768px){.curator-picker-grid{grid-template-columns:repeat(6,minmax(0,1fr))}}@media (min-width:1280px){.curator-picker-grid{grid-template-columns:repeat(8,minmax(0,1fr))}}@media (min-width:1536px){.curator-picker-grid{grid-template-columns:repeat(10,minmax(0,1fr))}}.filepond--panel{border-width:2px;border-style:dashed;border-color:rgba(var(--gray-950),.05);background-color:initial}:is(.dark .filepond--panel){border-color:#fff3}.curator-panel>.fi-modal-window,[wire\:key*=open_curation_panel]>.fi-modal-window,[wire\:key*=open_curator_picker]>.fi-modal-window{padding:0!important}.curator-panel>.fi-modal-window>.fi-modal-header,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgba(var(--gray-300),var(--tw-border-opacity));padding:.5rem 1rem}:is(.dark .curator-panel>.fi-modal-window>.fi-modal-header),:is(.dark [wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header),:is(.dark [wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header){--tw-border-opacity:1;border-color:rgba(var(--gray-800),var(--tw-border-opacity))}.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-heading,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-heading,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-heading{font-size:1rem;line-height:1.5rem}.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-close-btn,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn{margin-block-start:-.75rem}.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:focus,.curator-panel>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:hover,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:focus,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:hover,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:focus,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-header .fi-modal-close-btn:hover{background-color:initial!important;--tw-text-opacity:1;color:rgba(var(--primary-500),var(--tw-text-opacity))}.curator-panel>.fi-modal-window>.fi-modal-content,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-content,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-content{position:relative}.curator-panel>.fi-modal-window>.fi-modal-footer,[wire\:key*=open_curation_panel]>.fi-modal-window>.fi-modal-footer,[wire\:key*=open_curator_picker]>.fi-modal-window>.fi-modal-footer{padding-bottom:0} \ No newline at end of file diff --git a/resources/views/components/modals/curator-panel.blade.php b/resources/views/components/modals/curator-panel.blade.php index 999987b2..ad91b910 100644 --- a/resources/views/components/modals/curator-panel.blade.php +++ b/resources/views/components/modals/curator-panel.blade.php @@ -37,7 +37,7 @@ class="curator-panel h-full absolute inset-0 flex flex-col" > -
+
+
-
+

@@ -170,7 +220,7 @@ class="w-5 h-5" {{ empty($selected) ? trans('curator::views.panel.add_files') - : trans('curator::views.panel.edit_media') + : (count($selected) === 1 ? trans('curator::views.panel.edit_media') : null) }}

diff --git a/src/Components/Forms/CuratorPicker.php b/src/Components/Forms/CuratorPicker.php index 2e9a2c40..1d16b0e6 100644 --- a/src/Components/Forms/CuratorPicker.php +++ b/src/Components/Forms/CuratorPicker.php @@ -344,10 +344,6 @@ public function isConstrained(): bool public function isLimitedToDirectory(): bool { - if (!$this->getDirectory()) { - return false; - } - return $this->evaluate($this->isLimitedToDirectory) ?? config('curator.is_limited_to_directory'); } diff --git a/src/Components/Modals/Concerns/HasBreadcrumbs.php b/src/Components/Modals/Concerns/HasBreadcrumbs.php new file mode 100644 index 00000000..8b998fcb --- /dev/null +++ b/src/Components/Modals/Concerns/HasBreadcrumbs.php @@ -0,0 +1,38 @@ +breadcrumbs = [ + [ + 'label' => 'Disk', + 'name' => 'disk', + 'path' => $this->diskName, + 'parent_path' => null, + ], + ...$this->generateBreadcrumbs($this->directory, $this->directories) ?? [], + ]; + } + + public function generateBreadcrumbs($currentDir, $dirs): array + { + if (!$currentDir) { + return []; + } + + $item = is_string($currentDir) ? $dirs[$currentDir] : $currentDir; + + if ($item["parent_path"]) { + $crumbs = $this->generateBreadcrumbs($dirs[$item["parent_path"]], $dirs); + } + + $crumbs[] = $item; + + return $crumbs; + } +} \ No newline at end of file diff --git a/src/Components/Modals/Concerns/InteractsWithStorage.php b/src/Components/Modals/Concerns/InteractsWithStorage.php new file mode 100644 index 00000000..1d390344 --- /dev/null +++ b/src/Components/Modals/Concerns/InteractsWithStorage.php @@ -0,0 +1,51 @@ +diskName)->allDirectories(); + + $this->directories = collect($directories) + ->mapWithKeys(function ($item) { + $itemArray = explode("/", $item); + $name = array_pop($itemArray); + + return [ + $item => [ + "label" => Str::of($name) + ->replace("-", " ") + ->title() + ->toString(), + "name" => $name, + "path" => $item, + "parent_path" => implode("/", $itemArray) + ] + ]; + }) + ->toArray(); + } + + public function getSubDirectories(): void + { + $this->subDirectories = collect($this->directories) + ->where('parent_path', $this->directory ?? '') + ->toArray(); + } + + public function handleDirectoryChange(string $directory): void + { + $this->breadcrumbs = null; + $this->directory = $directory === $this->diskName ? null : $directory; + $this->files = $this->getFiles(); + } +} \ No newline at end of file diff --git a/src/Components/Modals/CuratorPanel.php b/src/Components/Modals/CuratorPanel.php index 697640ad..664a6277 100644 --- a/src/Components/Modals/CuratorPanel.php +++ b/src/Components/Modals/CuratorPanel.php @@ -3,6 +3,8 @@ namespace Awcodes\Curator\Components\Modals; use Awcodes\Curator\Components\Forms\Uploader; +use Awcodes\Curator\Components\Modals\Concerns\InteractsWithStorage; +use Awcodes\Curator\Components\Modals\Concerns\HasBreadcrumbs; use Awcodes\Curator\Models\Media; use Awcodes\Curator\PathGenerators\Contracts\PathGenerator; use Awcodes\Curator\Resources\MediaResource; @@ -21,7 +23,6 @@ use Illuminate\Support\Arr; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Storage; -use Illuminate\Support\Str; use Livewire\Attributes\On; use Livewire\Component; use Livewire\WithPagination; @@ -31,6 +32,8 @@ class CuratorPanel extends Component implements HasForms, HasActions { use InteractsWithActions; use InteractsWithForms; + use InteractsWithStorage; + use HasBreadcrumbs; use WithPagination; public array $acceptedFileTypes = []; @@ -39,7 +42,7 @@ class CuratorPanel extends Component implements HasForms, HasActions public ?array $data = []; - public string $directory = 'media'; + public ?string $directory = null; public string $diskName = 'public'; @@ -99,9 +102,17 @@ class CuratorPanel extends Component implements HasForms, HasActions public string $defaultSort = 'desc'; + public bool $shouldPrefetchFiles = false; + public function mount(): void { $this->form->fill(); + + $this->getDirectories(); + + if ($this->shouldPrefetchFiles) { + $this->files = $this->getFiles(); + } } #[On('open-modal')] @@ -131,6 +142,7 @@ public function openModal(string $id, array $settings = []): void $this->types = $settings['types']; $this->visibility = $settings['visibility']; + $this->breadcrumbs[] = $this->directory; $this->files = $this->getFiles(); $this->form->fill(); @@ -198,12 +210,16 @@ public function getFiles(int $page = 0, bool $excludeSelected = false): array ->when($this->isLimitedToDirectory, function ($query) { return $query->where('directory', $this->directory); }) - ->when($this->types, function ($query) { + ->when(filled($this->types), function ($query) { $types = $this->types; $query = $query->whereIn('type', $types); $wildcardTypes = collect($types)->filter(fn($type) => str_contains($type, '*')); $wildcardTypes?->map(fn($type) => $query->orWhere('type', 'LIKE', str_replace('*', '%', $type))); + if ($this->isLimitedToDirectory) { + $query->where('directory', $this->directory); + } + return $query; }) ->orderBy('created_at', $this->defaultSort); @@ -232,6 +248,9 @@ public function getFiles(int $page = 0, bool $excludeSelected = false): array $this->context = count($this->selected) === 1 ? 'edit' : 'create'; } + $this->getSubDirectories(); + $this->getBreadCrumbs(); + return collect($items)->map(function ($item) { return $item->toArray(); })->toArray(); diff --git a/src/Concerns/CanUploadFiles.php b/src/Concerns/CanUploadFiles.php index 3ff68672..ad3dee5c 100644 --- a/src/Concerns/CanUploadFiles.php +++ b/src/Concerns/CanUploadFiles.php @@ -59,7 +59,7 @@ public function getDiskName(): string return $this->evaluate($this->diskName) ?? config('curator.disk'); } - public function getDirectory(): string + public function getDirectory(): ?string { return $this->evaluate($this->directory) ?? config('curator.directory'); }