Add archived document PDF viewing and download route
This commit is contained in:
parent
b3e626b613
commit
a506eba604
|
|
@ -1,8 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Filament\Pages\Strumenti;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Documento;
|
||||
use App\Models\MovimentoContabile;
|
||||
use App\Models\Stabile;
|
||||
|
|
@ -10,13 +8,14 @@
|
|||
use App\Services\Documenti\PdfTextExtractionService;
|
||||
use App\Support\StabileContext;
|
||||
use BackedEnum;
|
||||
use Carbon\Carbon;
|
||||
use Dompdf\Dompdf;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Pages\Page;
|
||||
use Filament\Tables\Columns\BadgeColumn;
|
||||
|
|
@ -30,12 +29,16 @@
|
|||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Livewire\Attributes\Url;
|
||||
use UnitEnum;
|
||||
|
||||
class DocumentiArchivio extends Page implements HasTable
|
||||
{
|
||||
use InteractsWithTable;
|
||||
|
||||
#[Url( as : 'tab')]
|
||||
public string $hubTab = 'archivio-digitale';
|
||||
|
||||
protected static ?string $navigationLabel = 'Documenti (PDF)';
|
||||
|
||||
protected static ?string $title = 'Documenti (PDF)';
|
||||
|
|
@ -48,7 +51,7 @@ class DocumentiArchivio extends Page implements HasTable
|
|||
|
||||
protected static ?string $slug = 'strumenti/documenti';
|
||||
|
||||
protected string $view = 'filament.pages.gescon.table';
|
||||
protected string $view = 'filament.pages.strumenti.documenti-archivio';
|
||||
|
||||
public static function canAccess(): bool
|
||||
{
|
||||
|
|
@ -59,9 +62,15 @@ public static function canAccess(): bool
|
|||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->hubTab = $this->normalizeHubTab($this->hubTab);
|
||||
$this->mountInteractsWithTable();
|
||||
}
|
||||
|
||||
public function selectHubTab(string $tab): void
|
||||
{
|
||||
$this->hubTab = $this->normalizeHubTab($tab);
|
||||
}
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
|
|
@ -180,6 +189,23 @@ public function table(Table $table): Table
|
|||
->options($this->getCategorieOptions()),
|
||||
])
|
||||
->actions([
|
||||
Action::make('visualizza_pdf')
|
||||
->label('Vedi PDF')
|
||||
->icon('heroicon-o-eye')
|
||||
->visible(fn(Documento $record) => $this->hasPdf($record))
|
||||
->modalHeading(fn(Documento $record): string => trim((string) ($record->nome ?: 'Documento PDF')))
|
||||
->modalWidth('7xl')
|
||||
->modalContent(function (Documento $record) {
|
||||
$openUrl = route('filament.documenti.download', $record);
|
||||
|
||||
return view('filament.modals.pdf-viewer', [
|
||||
'url' => $openUrl . '?inline=1',
|
||||
'openUrl' => $openUrl,
|
||||
'title' => trim((string) ($record->nome ?: 'Documento PDF')),
|
||||
]);
|
||||
})
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelActionLabel('Chiudi'),
|
||||
Action::make('scarica_pdf')
|
||||
->label('PDF')
|
||||
->icon('heroicon-o-arrow-down-tray')
|
||||
|
|
@ -213,6 +239,73 @@ private function getCategorieOptions(): array
|
|||
];
|
||||
}
|
||||
|
||||
public function getHubStatsProperty(): array
|
||||
{
|
||||
$query = $this->getTableQuery();
|
||||
|
||||
return [
|
||||
'documenti' => (clone $query)->count(),
|
||||
'archiviati' => (clone $query)->where('archiviato', true)->count(),
|
||||
'in_scadenza' => (clone $query)->whereNotNull('data_scadenza')->whereDate('data_scadenza', '<=', now()->addDays(30)->toDateString())->count(),
|
||||
'template_drive' => count($this->getDriveTemplateFoldersProperty()),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function getDriveTemplateFoldersProperty(): array
|
||||
{
|
||||
$items = config('netgescon.google.drive_template_folders', []);
|
||||
$yearRoot = trim((string) config('netgescon.google.drive_template_year_root', ''));
|
||||
$yearModel = trim((string) config('netgescon.google.drive_template_year_model', ''));
|
||||
|
||||
$folders = is_array($items)
|
||||
? array_values(array_filter(array_map('strval', $items), fn(string $item) : bool => trim($item) !== ''))
|
||||
: [];
|
||||
|
||||
if ($yearRoot !== '' && $yearModel !== '') {
|
||||
foreach ($folders as $folder) {
|
||||
$folders[] = $yearRoot . '/' . $yearModel . '/' . $folder;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($folders));
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function getAudienceGroupsProperty(): array
|
||||
{
|
||||
return [
|
||||
'Condomini',
|
||||
'Inquilini',
|
||||
'Fornitori',
|
||||
'Collaboratori interni',
|
||||
'Amministratore',
|
||||
'Studio completo',
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function getArchivioFisicoTypesProperty(): array
|
||||
{
|
||||
return ['Faldone', 'Scatola', 'Cartella', 'Busta'];
|
||||
}
|
||||
|
||||
public function getMnemonicCodeHintProperty(): ?string
|
||||
{
|
||||
$stabile = $this->resolveActiveStabile();
|
||||
if (! $stabile instanceof Stabile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$label = Str::upper((string) ($stabile->denominazione ?? 'STABILE'));
|
||||
$letters = preg_replace('/[^A-Z]/', '', Str::ascii($label)) ?: 'STB';
|
||||
$digits = preg_replace('/\D/', '', $label);
|
||||
$prefix = str_pad(substr($letters, 0, 3), 3, 'X');
|
||||
$suffix = str_pad(substr($digits !== '' ? $digits : (string) $stabile->id, -5), 5, '0', STR_PAD_LEFT);
|
||||
|
||||
return $prefix . $suffix;
|
||||
}
|
||||
|
||||
private function getDocumentoFormSchema(): array
|
||||
{
|
||||
return [
|
||||
|
|
@ -306,6 +399,23 @@ private function getDefaultStabileId(): ?int
|
|||
return StabileContext::accessibleStabili($user)->first()?->id;
|
||||
}
|
||||
|
||||
private function normalizeHubTab(string $tab): string
|
||||
{
|
||||
$allowed = ['archivio-digitale', 'template-drive', 'archivio-fisico', 'permessi'];
|
||||
|
||||
return in_array($tab, $allowed, true) ? $tab : 'archivio-digitale';
|
||||
}
|
||||
|
||||
private function resolveActiveStabile(): ?Stabile
|
||||
{
|
||||
$user = Auth::user();
|
||||
if (! $user instanceof User) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return StabileContext::getActiveStabile($user);
|
||||
}
|
||||
|
||||
private function getMovimentiOptions(int $stabileId): array
|
||||
{
|
||||
if ($stabileId <= 0) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers\Filament;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DocumentoStabile;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class DocumentoStabileDownloadController extends Controller
|
||||
{
|
||||
public function download(Request $request, DocumentoStabile $documentoStabile)
|
||||
{
|
||||
$path = is_string($documentoStabile->percorso_file) ? trim((string) $documentoStabile->percorso_file) : '';
|
||||
if ($path === '') {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$selectedDisk = null;
|
||||
if (Storage::disk('public')->exists($path)) {
|
||||
$selectedDisk = 'public';
|
||||
} elseif (Storage::disk('local')->exists($path)) {
|
||||
$selectedDisk = 'local';
|
||||
}
|
||||
|
||||
if (! $selectedDisk) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$filename = is_string($documentoStabile->nome_originale) && trim((string) $documentoStabile->nome_originale) !== ''
|
||||
? trim((string) $documentoStabile->nome_originale)
|
||||
: ((is_string($documentoStabile->nome_file) && trim((string) $documentoStabile->nome_file) !== '')
|
||||
? trim((string) $documentoStabile->nome_file)
|
||||
: ('documento-stabile-' . (int) $documentoStabile->id . '.pdf'));
|
||||
|
||||
$filename = str_replace(["\r", "\n", '"'], '', $filename);
|
||||
|
||||
$documentoStabile->incrementaDownload();
|
||||
|
||||
if ($request->boolean('inline')) {
|
||||
return response()->file(Storage::disk($selectedDisk)->path($path), [
|
||||
'Content-Disposition' => 'inline; filename="' . $filename . '"',
|
||||
]);
|
||||
}
|
||||
|
||||
return Storage::disk($selectedDisk)->download($path, $filename);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -29,7 +28,7 @@ class DocumentoStabile extends Model
|
|||
'versione',
|
||||
'downloads',
|
||||
'ultimo_accesso',
|
||||
'caricato_da'
|
||||
'caricato_da',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
@ -39,14 +38,14 @@ class DocumentoStabile extends Model
|
|||
'downloads' => 'integer',
|
||||
'versione' => 'integer',
|
||||
'dimensione' => 'integer',
|
||||
'ultimo_accesso' => 'datetime'
|
||||
'ultimo_accesso' => 'datetime',
|
||||
];
|
||||
|
||||
protected $dates = [
|
||||
'data_scadenza',
|
||||
'ultimo_accesso',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -106,7 +105,9 @@ public function scopeScaduti($query)
|
|||
public function getDimensioneFormattataAttribute()
|
||||
{
|
||||
$bytes = $this->dimensione;
|
||||
if ($bytes === 0) return '0 Bytes';
|
||||
if ($bytes === 0) {
|
||||
return '0 Bytes';
|
||||
}
|
||||
|
||||
$k = 1024;
|
||||
$sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
|
|
@ -170,11 +171,11 @@ public function getStatoScadenzaAttribute()
|
|||
*/
|
||||
public function getUrlDownloadAttribute()
|
||||
{
|
||||
if (is_string($this->percorso_file) && trim($this->percorso_file) !== '' && Storage::disk('public')->exists($this->percorso_file)) {
|
||||
return Storage::disk('public')->url($this->percorso_file);
|
||||
if (! $this->fileEsiste()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
return route('filament.documenti-stabili.download', $this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -182,7 +183,13 @@ public function getUrlDownloadAttribute()
|
|||
*/
|
||||
public function getUrlViewAttribute()
|
||||
{
|
||||
return $this->url_download;
|
||||
$downloadUrl = $this->url_download;
|
||||
|
||||
if (! is_string($downloadUrl) || trim($downloadUrl) === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $downloadUrl . '?inline=1';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -237,7 +244,7 @@ public static function categorie()
|
|||
'bancari' => 'Documenti Bancari',
|
||||
'legali' => 'Documenti Legali',
|
||||
'assemblee' => 'Verbali Assemblee',
|
||||
'altri' => 'Altri'
|
||||
'altri' => 'Altri',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +261,7 @@ public static function coloriCategorie()
|
|||
'bancari' => 'secondary',
|
||||
'legali' => 'danger',
|
||||
'assemblee' => 'dark',
|
||||
'altri' => 'light'
|
||||
'altri' => 'light',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
<div class="-m-6 space-y-3 p-2">
|
||||
@php
|
||||
$title = isset($title) && is_string($title) && trim($title) !== '' ? trim($title) : 'Documento PDF';
|
||||
$openUrl = isset($openUrl) && is_string($openUrl) && trim($openUrl) !== '' ? trim($openUrl) : $url;
|
||||
@endphp
|
||||
|
||||
<div class="flex items-center justify-end gap-2 px-4 pt-4">
|
||||
<div class="mr-auto pr-4 text-sm font-semibold text-slate-800">{{ $title }}</div>
|
||||
<a
|
||||
href="{{ $url }}"
|
||||
href="{{ $openUrl }}"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="inline-flex items-center rounded-md bg-slate-800 px-3 py-1.5 text-xs font-medium text-white hover:bg-slate-700"
|
||||
|
|
|
|||
|
|
@ -586,6 +586,8 @@
|
|||
Route::middleware(['role:super-admin|admin|amministratore|collaboratore'])->prefix('admin-filament')->group(function () {
|
||||
Route::get('documenti/{documento}/download', [\App\Http\Controllers\Filament\DocumentiPrintController::class, 'download'])
|
||||
->name('filament.documenti.download');
|
||||
Route::get('documenti-stabili/{documentoStabile}/download', [\App\Http\Controllers\Filament\DocumentoStabileDownloadController::class, 'download'])
|
||||
->name('filament.documenti-stabili.download');
|
||||
Route::get('documenti/{documento}/etichetta', [\App\Http\Controllers\Filament\DocumentiPrintController::class, 'etichetta'])
|
||||
->name('filament.documenti.etichetta');
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user