Skip to content

Commit

Permalink
ImageLibrary: add disk option (#261)
Browse files Browse the repository at this point in the history
* ImageLibrary: add `disk` option

* WIP

* Add hover:opactity on ImageGallery
  • Loading branch information
robsontenorio authored Jan 10, 2024
1 parent 1e5c5f8 commit 25961e0
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 33 deletions.
71 changes: 45 additions & 26 deletions src/Traits/WithMediaSync.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
namespace Mary\Traits;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Str;

trait WithMediaSync
{
// Remove media
public function removeMedia(string $uuid, string $filesModelName, string $library, string $path): void
public function removeMedia(string $uuid, string $filesModelName, string $library, string $url): void
{
// Updates library
$this->{$library} = $this->{$library}->filter(fn($image) => $image['uuid'] != $uuid);

// Remove file
$name = str($path)->after('preview-file/')->before('?expires')->toString();
$name = str($url)->after('preview-file/')->before('?expires')->toString();
$this->{$filesModelName} = collect($this->{$filesModelName})->filter(fn($file) => $file->getFilename() != $name)->all();
}

Expand All @@ -32,7 +32,7 @@ public function refreshMediaSources(string $filesModelName, string $library)
{
// New files area
foreach ($this->{$filesModelName}['*'] ?? [] as $key => $file) {
$this->{$library} = $this->{$library}->add(['uuid' => Str::uuid()->toString(), 'path' => $file->temporaryUrl()]);
$this->{$library} = $this->{$library}->add(['uuid' => Str::uuid()->toString(), 'url' => $file->temporaryUrl()]);

$key = $this->{$library}->keys()->last();
$this->{$filesModelName}[$key] = $file;
Expand All @@ -43,39 +43,58 @@ public function refreshMediaSources(string $filesModelName, string $library)

//Replace existing files
foreach ($this->{$filesModelName} as $key => $file) {
$this->{$library} = $this->{$library}->replace([
$key => ['uuid' => Str::uuid()->toString(), 'path' => $file->temporaryUrl()]
]);
$media = $this->{$library}->get($key);
$media['url'] = $file->temporaryUrl();

$this->{$library} = $this->{$library}->replace([$key => $media]);
}

$this->validateOnly($filesModelName . '.*');
}

// Storage files into permanent area and updates the model with fresh sources
public function syncMedia(Model $model, mixed $files, Collection $library, string $storage_subpath = '', $model_field = 'library', string $visibility = 'public'): void
{
$uploads = collect();
public function syncMedia(
Model $model,
string $library = 'library',
string $files = 'files',
string $storage_subpath = '',
$model_field = 'library',
string $visibility = 'public',
string $disk = 'public'
): void {
// Store files
foreach ($this->{$files} as $index => $file) {
$media = $this->{$library}->get($index);
$name = $this->getFileName($media);

$file = Storage::disk($disk)->putFileAs($storage_subpath, $file, $name, $visibility);
$url = Storage::disk($disk)->url($file);

// Update library
$media['url'] = $url . "?updated_at=" . time();
$media['path'] = str($storage_subpath)->finish('/')->append($name)->toString();
$this->{$library} = $this->{$library}->replace([$index => $media]);
}

// Delete removed files from library
$diffs = $model->{$model_field}?->filter(fn($item) => $this->{$library}->doesntContain('uuid', $item['uuid'])) ?? [];

// Storage files
foreach ($files as $file) {
$uploads->add(['url' => "/storage/" . $file->store($storage_subpath, $visibility), 'filename' => $file->getFilename()]);
foreach ($diffs as $diff) {
Storage::disk($disk)->delete($diff['path']);
}

// Replace temporary sources for permanent sources
$images = $library
->map(function ($item) use ($uploads) {
$upload = $uploads->filter(function ($upload) use ($item) {
return str($item['path'])->contains($upload['filename']);
})->first();
// Updates model
$model->update([$model_field => $this->{$library}]);

if ($upload) {
$item['path'] = $upload['url'];
}
// Resets files
$this->{$files} = [];
}

return $item;
});
private function getFileName(?array $media): ?string
{
$name = $media['uuid'] ?? null;
$extension = str($media['url'] ?? null)->after('.')->before('?expires')->toString();

// Updates model
$model->update([$model_field => $images]);
return "$name.$extension";
}
}
2 changes: 1 addition & 1 deletion src/View/Components/ImageGallery.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class="carousel-item"
$el.setAttribute('data-pswp-height', document.getElementById('image-{{ $uuid }}-{{ $loop->index }}').naturalHeight);
"
>
<img src="{{ $image }}" class="object-cover" id="image-{{ $uuid }}-{{ $loop->index }}" />
<img src="{{ $image }}" class="object-cover hover:opacity-70" id="image-{{ $uuid }}-{{ $loop->index }}" />
</a>
@endforeach
</div>
Expand Down
13 changes: 7 additions & 6 deletions src/View/Components/ImageLibrary.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public function cropSetup(): string
return json_encode(array_merge([
'autoCropArea' => 1,
'viewMode' => 1,
'dragMode' => 'move'
'dragMode' => 'move',
'checkCrossOrigin' => false,
], $this->cropConfig));
}

Expand Down Expand Up @@ -100,9 +101,9 @@ public function render(): View|Closure|string
this.cropper = new Cropper(this.imageCrop, {{ $cropSetup() }});
},
removeMedia(uuid, path){
removeMedia(uuid, url){
this.indeterminate = true
$wire.removeMedia(uuid, '{{ $modelName() }}', '{{ $libraryName() }}', path).then(() => this.indeterminate = false)
$wire.removeMedia(uuid, '{{ $modelName() }}', '{{ $libraryName() }}', url).then(() => this.indeterminate = false)
},
refreshMediaOrder(order){
$wire.refreshMediaOrder(order, '{{ $libraryName() }}')
Expand Down Expand Up @@ -151,7 +152,7 @@ class="border border-dotted border-primary rounded-lg"
<div wire:key="preview-{{ $image['uuid'] }}" class="py-2 pl-16 pr-10 tooltip" data-tip="{{ $changeText }}">
<!-- IMAGE -->
<img
src="{{ $image['path'] }}"
src="{{ $image['url'] }}"
class="h-24 cursor-pointer border-2 rounded-lg hover:scale-105 transition-all ease-in-out"
@click="document.getElementById('file-{{ $uuid}}-{{ $key }}').click()"
id="image-{{ $modelName().'.'.$key }}-{{ $uuid }}" />
Expand All @@ -174,7 +175,7 @@ class="hidden"
<!-- ACTIONS -->
<div class="absolute flex flex-col gap-2 top-3 left-3 cursor-pointer p-2 rounded-lg">
<x-mary-button @click="removeMedia('{{ $image['uuid'] }}', '{{ $image['path'] }}')" icon="o-x-circle" :tooltip="$removeText" class="btn-sm btn-ghost btn-circle" />
<x-mary-button @click="removeMedia('{{ $image['uuid'] }}', '{{ $image['url'] }}')" icon="o-x-circle" :tooltip="$removeText" class="btn-sm btn-ghost btn-circle" />
<x-mary-button @click="crop('image-{{ $modelName().'.'.$key }}-{{ $uuid }}')" icon="o-scissors" :tooltip="$cropText" class="btn-sm btn-ghost btn-circle" />
</div>
</div>
Expand All @@ -185,7 +186,7 @@ class="hidden"
<!-- CROP MODAL -->
<div @click.prevent="" x-ref="crop" wire:ignore>
<x-mary-modal id="maryCropModal{{ $uuid }}" x-ref="maryCropModal" :title="$cropTitleText" separator class="backdrop-blur-sm" persistent @keydown.window.esc.prevent="">
<img src="#" />
<img src="#" crossOrigin="Anonymous" />
<x-slot:actions>
<x-button :label="$cropCancelText" @click="close()" />
<x-button :label="$cropSaveText" class="btn-primary" @click="save()" />
Expand Down

0 comments on commit 25961e0

Please sign in to comment.