Add file import feature to vaults

This commit is contained in:
Bruno
2024-11-03 21:17:39 +00:00
parent ae969bca09
commit 7ef192a401
5 changed files with 177 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
<?php
namespace App\Actions;
use App\Models\Vault;
use App\Models\VaultNode;
use Illuminate\Http\File;
use App\Services\VaultFile;
use App\Services\VaultFiles\Note;
use App\Actions\GetPathFromVaultNode;
use Illuminate\Support\Facades\Storage;
class ProcessImportedFile
{
public function handle(Vault $vault, VaultNode $parent, string $fileName, string $filePath): void
{
$name = pathinfo($fileName, PATHINFO_FILENAME);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
if (!in_array($extension, VaultFile::extensions())) {
abort(400);
}
// Find new filename if it already exists
$counter = 0;
while (
$vault->nodes()
->where('parent_id', $parent->id)
->where('is_file', true)
->where('name', !$counter ? $name : $name . '-' . $counter)
->where('extension', $extension)
->exists()
) {
$counter++;
}
$name = !$counter ? $name : $name . '-' . $counter;
$content = null;
if (in_array($extension, Note::extensions())) {
$content = file_get_contents($filePath);
}
$node = $vault->nodes()->create([
'parent_id' => $parent->id,
'is_file' => true,
'name' => $name,
'extension' => $extension,
'content' => $content,
]);
if (!in_array($extension, Note::extensions())) {
$relativePath = (new GetPathFromVaultNode())->handle($node);
$savePath = pathinfo($relativePath, PATHINFO_DIRNAME);
$saveName = pathinfo($relativePath, PATHINFO_BASENAME);
Storage::putFileAs($savePath, new File($filePath), $saveName);
}
}
}
+78
View File
@@ -0,0 +1,78 @@
<?php
namespace App\Livewire\Modals;
use App\Models\Vault;
use App\Models\VaultNode;
use App\Services\VaultFile;
use Illuminate\Support\Arr;
use Livewire\Attributes\On;
use Livewire\WithFileUploads;
use Livewire\Attributes\Validate;
use App\Actions\ProcessImportedFile;
class ImportFile extends Modal
{
use WithFileUploads;
public Vault $vault;
public VaultNode $parent;
public bool $show;
public string $fileMimes;
#[Validate]
public $file;
public function rules(): array
{
return [
'file' => [
'required',
'mimes:' . Arr::join(VaultFile::extensions(), ','),
],
];
}
public function mount(Vault $vault): void
{
$this->authorize('view', $vault);
$this->vault = $vault;
$this->show = false;
$this->fileMimes = Arr::join(VaultFile::extensions(true), ',');
}
#[On('open-modal')]
public function open(?VaultNode $parent = null): void
{
$this->parent = $parent;
if ($this->parent->exists) {
$this->authorize('update', $this->parent->vault);
// Make sure submitted parent node is a folder
if ($this->parent->is_file) {
abort(400);
}
}
$this->openModal();
}
public function updatedFile(): void
{
$this->validate();
$fileName = $this->file->getClientOriginalName();
$filePath = $this->file->getRealPath();
(new ProcessImportedFile())->handle($this->vault, $this->parent, $fileName, $filePath);
$this->dispatch('node-updated');
$this->closeModal();
}
public function render()
{
return view('livewire.modals.importFile');
}
}
@@ -29,6 +29,12 @@
{{ __('New folder') }}
</x-menu.item>
<x-menu.item
@click="$wire.dispatchTo('modals.import-file', 'open-modal', { parent: {{ $node->id }} })">
<x-icons.arrowUpTray class="w-4 h-4" />
{{ __('Import file') }}
</x-menu.item>
<x-menu.item @click="$wire.dispatchTo('modals.edit-node', 'open-modal', { node: {{ $node->id }} })">
<x-icons.pencilSquare class="w-4 h-4" />
{{ __('Rename') }}
@@ -0,0 +1,29 @@
<x-modal wire:model="show">
<x-modal.panel>
<x-form wire:submit="import">
<div x-data="{ uploading: false, progress: 0 }" x-on:livewire-upload-start="uploading = true"
x-on:livewire-upload-finish="uploading = false" x-on:livewire-upload-cancel="uploading = false"
x-on:livewire-upload-error="uploading = false"
x-on:livewire-upload-progress="progress = $event.detail.progress"
class="flex flex-col items-center justify-center w-full h-48 border-2 border-dashed rounded-lg border-light-base-300 dark:border-base-500">
<label for="file-upload"
class="flex flex-col items-center justify-center w-full h-full gap-2 text-base font-medium cursor-pointer">
<h6 class="font-semibold">{{ __('Browse file to import') }}</h6>
<span class="text-sm">{{ __('Image, video, audio, note or pdf file') }}</span>
<span class="text-sm">{{ __('Max size ') . ini_get('upload_max_filesize') }}</span>
@error('file')
<p class="text-sm text-center text-error-500" aria-live="assertive">{{ $message }}</p>
@enderror
<!-- Progress Bar -->
<div x-show="uploading">
<progress max="100" x-bind:value="progress" class="w-64 h-1 mt-2"></progress>
</div>
</label>
<input type="file" id="file-upload" class="hidden" wire:model="file" accept="{{ $fileMimes }}" />
</div>
</x-form>
</x-modal.panel>
</x-modal>
@@ -49,6 +49,11 @@
{{ __('New folder') }}
</x-menu.item>
<x-menu.item @click="$wire.dispatchTo('modals.import-file', 'open-modal')">
<x-icons.arrowUpTray class="w-4 h-4" />
{{ __('Import file') }}
</x-menu.item>
<x-modal wire:model="showEditModal">
<x-modal.open>
<x-menu.item>
@@ -168,6 +173,7 @@
</x-layouts.appMain>
<livewire:modals.add-node :$vault />
<livewire:modals.import-file :$vault />
<livewire:modals.edit-node :$vault />
<livewire:modals.search-node :$vault />
</div>