From b7de070d0f524b5c19f98f6e50d57c2f980a53ee Mon Sep 17 00:00:00 2001 From: bernardhanna Date: Mon, 30 Mar 2026 15:54:34 +0100 Subject: [PATCH] upload images to nova --- app/Nova/Actions/BulkUploadMediaFiles.php | 53 ++++++++++++++++++++--- app/Nova/MediaUpload.php | 28 ++++++++---- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/app/Nova/Actions/BulkUploadMediaFiles.php b/app/Nova/Actions/BulkUploadMediaFiles.php index 52afb53c5..fab097f3d 100644 --- a/app/Nova/Actions/BulkUploadMediaFiles.php +++ b/app/Nova/Actions/BulkUploadMediaFiles.php @@ -4,6 +4,7 @@ use App\MediaUpload; use Illuminate\Bus\Queueable; +use Illuminate\Http\UploadedFile; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Collection; @@ -33,15 +34,11 @@ class BulkUploadMediaFiles extends Action */ public function handle(ActionFields $fields, Collection $models) { - $uploadedFiles = $fields->files ?? request()->file('files'); - if (!$uploadedFiles) { + $uploadedFiles = $this->collectUploadedFiles($fields); + if (empty($uploadedFiles)) { return Action::danger('Please select one or more files.'); } - if (!is_array($uploadedFiles)) { - $uploadedFiles = [$uploadedFiles]; - } - $allowedExtensions = [ 'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'pdf', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'txt', @@ -100,6 +97,7 @@ public function fields(NovaRequest $request): array File::make('Files', 'files') ->withMeta([ 'extraAttributes' => [ + 'name' => 'files[]', 'multiple' => true, 'accept' => '.jpg,.jpeg,.png,.gif,.webp,.svg,.pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.txt', ], @@ -109,6 +107,49 @@ public function fields(NovaRequest $request): array ]; } + /** + * Collect uploaded files from Nova action fields + raw request payload. + * + * @return UploadedFile[] + */ + protected function collectUploadedFiles(ActionFields $fields): array + { + $candidates = []; + + if (isset($fields->files)) { + $candidates[] = $fields->files; + } + + $requestFiles = request()->allFiles(); + if (!empty($requestFiles)) { + $candidates[] = $requestFiles; + } + + $flatten = function ($value) use (&$flatten): array { + if ($value instanceof UploadedFile) { + return [$value]; + } + + if (!is_array($value)) { + return []; + } + + $result = []; + foreach ($value as $item) { + $result = array_merge($result, $flatten($item)); + } + + return $result; + }; + + $files = []; + foreach ($candidates as $candidate) { + $files = array_merge($files, $flatten($candidate)); + } + + return $files; + } + /** * Indicate that this action can be run without any models. */ diff --git a/app/Nova/MediaUpload.php b/app/Nova/MediaUpload.php index c260d9a05..75c281cb4 100644 --- a/app/Nova/MediaUpload.php +++ b/app/Nova/MediaUpload.php @@ -55,20 +55,16 @@ public function fields(Request $request): array ->help('Uploads directly to S3 disk "resources" under folder "nova/uploads".'), Text::make('URL', function () { - if (empty($this->resolved_url)) { - return '-'; - } - - $url = $this->resolved_url; - - return '' . e($url) . ''; + return $this->renderUrlWithCopy($this->resolved_url); }) ->asHtml() ->onlyOnDetail(), Text::make('URL', function () { - return $this->resolved_url ?: '-'; - })->onlyOnIndex(), + return $this->renderUrlWithCopy($this->resolved_url); + }) + ->asHtml() + ->onlyOnIndex(), ]; } @@ -83,4 +79,18 @@ public function actions(Request $request): array new BulkUploadMediaFiles, ]; } + + protected function renderUrlWithCopy(?string $url): string + { + if (empty($url)) { + return '-'; + } + + $escapedUrl = e($url); + $jsonUrl = json_encode($url, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP); + $copyScript = "navigator.clipboard.writeText({$jsonUrl}).then(function(){alert('URL copied to clipboard');}).catch(function(){window.prompt('Copy URL:', {$jsonUrl});}); return false;"; + + return '' . $escapedUrl . '' + . ' '; + } }