Skip to content

Commit 8aa395e

Browse files
scott graysonscott grayson
authored andcommitted
missing and unpreviewable file messages
1 parent f1c1057 commit 8aa395e

File tree

4 files changed

+173
-45
lines changed

4 files changed

+173
-45
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ composer.lock
88
coverage
99
docs
1010
node_modules
11+
package-lock.json
1112
phpunit.xml
1213
phpstan.neon
1314
testbench.yaml

resources/css/filament-library.css

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* Filament Library Plugin Styles */
2+
3+
/* Unpreviewable File Section */
4+
.filament-library-unpreviewable {
5+
text-align: center !important;
6+
display: flex !important;
7+
flex-direction: column !important;
8+
gap: 1.5rem !important;
9+
align-items: center !important;
10+
padding: 2rem !important;
11+
}
12+
13+
.filament-library-unpreviewable-message {
14+
font-size: 1.125rem !important; /* text-lg equivalent */
15+
color: #6b7280 !important; /* text-gray-600 equivalent */
16+
font-weight: 400 !important;
17+
line-height: 1.5 !important;
18+
margin-bottom: 1rem !important;
19+
/* Force cache bust - v3 */
20+
}
21+
22+
/* Dark mode support */
23+
@media (prefers-color-scheme: dark) {
24+
.filament-library-unpreviewable-message {
25+
color: #9ca3af; /* text-gray-400 equivalent for dark mode */
26+
}
27+
}
28+
29+
.filament-library-unpreviewable-button {
30+
display: flex !important;
31+
justify-content: center !important;
32+
width: 100% !important;
33+
}
34+
35+
/* PDF Container Styles */
36+
.pdf-container {
37+
width: 100%;
38+
height: calc(100vh - 80px); /* 100vh minus estimated top nav height */
39+
border: none;
40+
border-radius: 0.5rem;
41+
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
42+
}
43+
44+
/* Video Container Styles */
45+
.video-container {
46+
width: 100%;
47+
height: 400px;
48+
border-radius: 0.5rem;
49+
overflow: hidden;
50+
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
51+
}
52+
53+
.video-container video {
54+
width: 100%;
55+
height: 100%;
56+
object-fit: cover;
57+
}
Lines changed: 93 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,110 @@
11
@php
22
$media = $record->getFirstMedia('files');
33
$mimeType = $media?->mime_type;
4-
$fileUrl = $media?->getUrl();
54
6-
// Ensure HTTPS URLs to avoid mixed content issues
7-
if ($fileUrl && str_starts_with($fileUrl, 'http://')) {
8-
$fileUrl = str_replace('http://', 'https://', $fileUrl);
5+
// Try temporary URL first, fallback to regular URL
6+
$fileUrl = null;
7+
if ($media) {
8+
try {
9+
$fileUrl = $media->getTemporaryUrl(now()->addMinutes(60));
10+
} catch (\Exception $e) {
11+
// Fallback to regular URL if temporary URLs not supported
12+
$fileUrl = $media->getUrl();
13+
14+
// Ensure HTTPS for security
15+
if (str_starts_with($fileUrl, 'http://')) {
16+
$fileUrl = str_replace('http://', 'https://', $fileUrl);
17+
}
18+
}
919
}
1020
1121
// Get file extension for better type detection
1222
$extension = strtolower(pathinfo($media?->name, PATHINFO_EXTENSION));
1323
@endphp
1424

25+
@php
26+
// Define previewable file types
27+
$previewableImages = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp'];
28+
$previewableDocuments = ['pdf'];
29+
$previewableVideos = ['mp4', 'webm', 'ogg', 'avi', 'mov'];
30+
$previewableAudio = ['mp3', 'wav', 'ogg', 'm4a', 'aac'];
31+
32+
// Check if file can be previewed
33+
$canPreview = false;
34+
$previewType = null;
35+
36+
if (str_starts_with($mimeType, 'image/') || in_array($extension, $previewableImages)) {
37+
$canPreview = true;
38+
$previewType = 'image';
39+
} elseif (in_array($extension, $previewableDocuments) || $mimeType === 'application/pdf') {
40+
$canPreview = true;
41+
$previewType = 'pdf';
42+
} elseif (str_starts_with($mimeType, 'video/') || in_array($extension, $previewableVideos)) {
43+
$canPreview = true;
44+
$previewType = 'video';
45+
} elseif (str_starts_with($mimeType, 'audio/') || in_array($extension, $previewableAudio)) {
46+
$canPreview = true;
47+
$previewType = 'audio';
48+
}
49+
@endphp
50+
1551
@if($media)
1652
<div class="w-full">
17-
@if(str_starts_with($mimeType, 'image/'))
18-
{{-- Image preview --}}
19-
<img src="{{ $fileUrl }}" alt="{{ $media->name }}" class="max-w-full h-auto rounded-lg shadow-lg">
20-
@elseif($mimeType === 'application/pdf' || $extension === 'pdf')
21-
{{-- PDF preview --}}
22-
<iframe src="{{ $fileUrl }}#toolbar=0&navpanes=0&scrollbar=1" class="w-full h-96 border rounded-lg" title="{{ $media->name }}"></iframe>
23-
@elseif($extension === 'md' || $extension === 'markdown')
24-
{{-- Markdown preview --}}
25-
<div class="border rounded-lg p-4 bg-white">
26-
<div class="mb-2 text-sm text-gray-500">Markdown Preview:</div>
27-
<iframe src="{{ $fileUrl }}" class="w-full h-96 border rounded-lg" title="{{ $media->name }}"></iframe>
28-
</div>
29-
@elseif(str_starts_with($mimeType, 'text/') || in_array($extension, ['txt', 'csv', 'json', 'xml', 'html', 'css', 'js']))
30-
{{-- Text file preview --}}
31-
<div class="border rounded-lg p-4 bg-white">
32-
<div class="mb-2 text-sm text-gray-500">Text Preview:</div>
33-
<iframe src="{{ $fileUrl }}" class="w-full h-96 border rounded-lg" title="{{ $media->name }}"></iframe>
34-
</div>
53+
@if($canPreview)
54+
@if($previewType === 'image')
55+
{{-- Image preview --}}
56+
<img src="{{ $fileUrl }}" alt="{{ $media->name }}" class="max-w-full h-auto rounded-lg shadow-lg">
57+
@elseif($previewType === 'pdf')
58+
{{-- PDF preview --}}
59+
<iframe src="{{ $fileUrl }}#toolbar=0&navpanes=0&scrollbar=1&view=FitH" title="{{ $media->name }}" class="pdf-container"></iframe>
60+
@elseif($previewType === 'video')
61+
{{-- Video preview --}}
62+
<div class="video-container">
63+
<video controls class="w-full h-full">
64+
<source src="{{ $fileUrl }}" type="{{ $mimeType }}">
65+
Your browser does not support the video tag.
66+
</video>
67+
</div>
68+
@elseif($previewType === 'audio')
69+
{{-- Audio preview --}}
70+
<div class="bg-gray-50 rounded-lg p-6">
71+
<div class="mb-2 text-sm text-gray-500">Audio Preview:</div>
72+
<audio controls class="w-full">
73+
<source src="{{ $fileUrl }}" type="{{ $mimeType }}">
74+
Your browser does not support the audio tag.
75+
</audio>
76+
</div>
77+
@endif
3578
@else
36-
{{-- Generic file info --}}
37-
<div class="bg-gray-50 border-2 border-dashed border-gray-300 rounded-lg p-8 text-center">
38-
<div class="text-gray-500 mb-4">
39-
<svg class="mx-auto h-12 w-12" fill="none" viewBox="0 0 24 24" stroke="currentColor">
40-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
41-
</svg>
79+
{{-- File cannot be previewed --}}
80+
<x-filament::section>
81+
<div class="filament-library-unpreviewable">
82+
<div class="filament-library-unpreviewable-message">
83+
This file type cannot be previewed. Please download to view.
84+
</div>
85+
86+
<div class="filament-library-unpreviewable-button">
87+
<x-filament::button
88+
tag="a"
89+
href="{{ $fileUrl }}"
90+
target="_blank"
91+
icon="heroicon-o-arrow-down-tray"
92+
color="primary"
93+
>
94+
Download File
95+
</x-filament::button>
96+
</div>
4297
</div>
43-
<h3 class="text-lg font-medium text-gray-900 mb-2">{{ $media->name }}</h3>
44-
<p class="text-sm text-gray-500 mb-4">{{ number_format($media->size / 1024 / 1024, 2) }} MB</p>
45-
<a href="{{ $fileUrl }}" target="_blank" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700">
46-
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
47-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
48-
</svg>
49-
Download File
50-
</a>
51-
</div>
98+
</x-filament::section>
5299
@endif
53100
</div>
101+
@else
102+
{{-- No file associated with this record --}}
103+
<x-filament::section>
104+
<div class="filament-library-unpreviewable">
105+
<div class="filament-library-unpreviewable-message">
106+
No file is currently associated with this item.
107+
</div>
108+
</div>
109+
</x-filament::section>
54110
@endif

src/Resources/Pages/ViewLibraryItem.php

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,24 @@ protected function getHeaderActions(): array
7070
->label('Download')
7171
->color('gray')
7272
->icon('heroicon-o-arrow-down-tray')
73-
->url(fn () => $this->getRecord()->getFirstMedia('files')->getUrl())
73+
->url(function () {
74+
$media = $this->getRecord()->getFirstMedia('files');
75+
76+
// Try temporary URL first, fallback to regular URL
77+
try {
78+
return $media->getTemporaryUrl(now()->addMinutes(60));
79+
} catch (\Exception $e) {
80+
// Fallback to regular URL if temporary URLs not supported
81+
$url = $media->getUrl();
82+
83+
// Ensure HTTPS for security
84+
if (str_starts_with($url, 'http://')) {
85+
$url = str_replace('http://', 'https://', $url);
86+
}
87+
88+
return $url;
89+
}
90+
})
7491
->openUrlInNewTab();
7592
}
7693

@@ -140,13 +157,10 @@ public function infolist(Schema $schema): Schema
140157
->columnSpanFull(),
141158

142159
// File preview for files
143-
Section::make()
144-
->schema([
145-
\Filament\Infolists\Components\ViewEntry::make('file_preview')
146-
->view('filament-library::infolists.components.file-preview')
147-
->viewData(fn () => ['record' => $record])
148-
])
149-
->visible(fn () => $record->type === 'file' && $record->getFirstMedia('files'))
160+
\Filament\Infolists\Components\ViewEntry::make('file_preview')
161+
->view('filament-library::infolists.components.file-preview')
162+
->viewData(fn () => ['record' => $record])
163+
->visible(fn () => $record->type === 'file')
150164
->columnSpanFull(),
151165

152166
// Item details section

0 commit comments

Comments
 (0)