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 . ''
+ . ' ';
+ }
}