clusev/app/Livewire/Files/Index.php

136 lines
3.7 KiB
PHP

<?php
namespace App\Livewire\Files;
use App\Livewire\Concerns\WithFleetContext;
use App\Services\FleetService;
use Livewire\Attributes\Layout;
use Livewire\Attributes\On;
use Livewire\Attributes\Title;
use Livewire\Component;
use Throwable;
#[Layout('layouts.app')]
#[Title('Dateien — Clusev')]
class Index extends Component
{
use WithFleetContext;
/** Current working directory in the SFTP browser. */
public string $path = '/';
public bool $connected = false;
public bool $ready = false;
/** @var array<int, array{name:string,type:string,size:?int,perms:string,owner:string,modified:string}> */
public array $entries = [];
public function mount(): void
{
// listing loads lazily via wire:init -> load()
}
/** Read the active server's directory over SSH; empty + offline on failure. */
public function load(): void
{
$this->entries = [];
$this->connected = false;
$active = $this->activeServer();
if ($active && $active->credential_exists) {
try {
$this->entries = app(FleetService::class)->files($active, $this->path);
$this->connected = true;
} catch (Throwable) {
$this->connected = false;
}
}
$this->ready = true;
}
public function open(string $name): void
{
$this->path = rtrim($this->path, '/').'/'.$name;
$this->load();
}
public function go(string $path): void
{
$this->path = $path !== '' ? $path : '/';
$this->load();
}
public function up(): void
{
$this->path = dirname($this->path) ?: '/';
$this->load();
}
/**
* Breadcrumb segments derived from $path (root first, then each folder).
*
* @return array<int, array{label: string, path: string}>
*/
public function getCrumbsProperty(): array
{
$crumbs = [['label' => '/', 'path' => '/']];
$acc = '';
foreach (array_filter(explode('/', $this->path)) as $segment) {
$acc .= '/'.$segment;
$crumbs[] = ['label' => $segment, 'path' => $acc];
}
return $crumbs;
}
/**
* Delete a file (R5): opens the confirm modal, which writes the AuditEvent
* and re-dispatches `fileConfirmed`. SFTP unlink is wired in behind this later.
*/
public function confirmDelete(string $name): void
{
$this->dispatch('openModal',
component: 'modals.confirm-action',
arguments: [
'heading' => 'Datei löschen',
'body' => "{$name}“ wird unwiderruflich aus {$this->path} entfernt.",
'confirmLabel' => 'Löschen',
'danger' => true,
'icon' => 'trash',
'auditAction' => 'file.delete',
'auditTarget' => rtrim($this->path, '/')."/{$name}",
'event' => 'fileConfirmed',
'params' => ['name' => $name],
'notify' => "{$name}“ gelöscht.",
],
);
}
/** Applies the confirmed deletion over SFTP, then reloads the directory. */
#[On('fileConfirmed')]
public function deleteEntry(string $name, FleetService $fleet): void
{
$active = $this->activeServer();
if ($active && $active->credential_exists) {
try {
$fleet->deleteFile($active, rtrim($this->path, '/').'/'.$name);
} catch (Throwable $e) {
$this->dispatch('notify', message: 'Löschen fehlgeschlagen: '.$e->getMessage());
return;
}
}
$this->load();
}
public function render()
{
return view('livewire.files.index');
}
}