diff --git a/resources/js/components/assets/Browser/Browser.vue b/resources/js/components/assets/Browser/Browser.vue index 40eb5ea7107..0ba7ae383b6 100644 --- a/resources/js/components/assets/Browser/Browser.vue +++ b/resources/js/components/assets/Browser/Browser.vue @@ -740,10 +740,7 @@ export default { }, existingUploadSelected(upload) { - const path = `${this.folder.path}/${upload.basename}`.replace(/^\/+/, ''); - const id = `${this.container.id}::${path}`; - - this.selectedAssets.push(id); + this.selectedAssets.push(upload.existingId); this.$emit('selections-updated', this.selectedAssets); }, diff --git a/resources/js/components/assets/Uploader.vue b/resources/js/components/assets/Uploader.vue index 6ec9948155d..a324eb99684 100644 --- a/resources/js/components/assets/Uploader.vue +++ b/resources/js/components/assets/Uploader.vue @@ -307,6 +307,7 @@ export default { upload.errorMessage = msg; upload.errorStatus = status; + upload.existingId = response?.existing; this.$emit('error', upload, this.uploads); this.processUploadQueue(); }, diff --git a/resources/js/components/fieldtypes/assets/AssetsFieldtype.vue b/resources/js/components/fieldtypes/assets/AssetsFieldtype.vue index c07eb1f1ccc..3a63bba2cc1 100644 --- a/resources/js/components/fieldtypes/assets/AssetsFieldtype.vue +++ b/resources/js/components/fieldtypes/assets/AssetsFieldtype.vue @@ -656,8 +656,7 @@ export default { }, uploadSelected(upload) { - const path = `${this.folder}/${upload.basename}`.replace(/^\/+/, ''); - const id = `${this.container.id}::${path}`; + const id = upload.existingId; this.uploads.splice(this.uploads.indexOf(upload), 1); diff --git a/resources/js/tests/components/fieldtypes/AssetsFieldtype.test.js b/resources/js/tests/components/fieldtypes/AssetsFieldtype.test.js index ff68cff46fa..4cb805f3786 100644 --- a/resources/js/tests/components/fieldtypes/AssetsFieldtype.test.js +++ b/resources/js/tests/components/fieldtypes/AssetsFieldtype.test.js @@ -33,22 +33,13 @@ const makeField = ({ axiosPost = vi.fn(() => Promise.resolve({ data: [] })), pro }); }; -test('selecting the existing file references it by the container id', () => { - const post = vi.fn(() => Promise.resolve({ data: [] })); - const field = makeField({ axiosPost: post }); - - field.vm.uploadSelected({ basename: 'user.png' }); - - expect(post).toHaveBeenCalledWith('assets-fieldtype', { assets: ['main::user.png'] }); -}); - -test('the existing file id includes the configured folder', () => { +test('selecting the existing file references the asset the server reported', () => { const post = vi.fn(() => Promise.resolve({ data: [] })); const field = makeField({ axiosPost: post, props: { config: { folder: 'sub' } } }); - field.vm.uploadSelected({ basename: 'user.png' }); + field.vm.uploadSelected({ basename: 'My File.PNG', existingId: 'main::sub/my-file.png' }); - expect(post).toHaveBeenCalledWith('assets-fieldtype', { assets: ['main::sub/user.png'] }); + expect(post).toHaveBeenCalledWith('assets-fieldtype', { assets: ['main::sub/my-file.png'] }); }); test('loading assets for a new value does not emit an update when the ids are unchanged', async () => { diff --git a/src/Http/Controllers/CP/Assets/AssetsController.php b/src/Http/Controllers/CP/Assets/AssetsController.php index 8aeb7585c95..3b7eb812b1f 100644 --- a/src/Http/Controllers/CP/Assets/AssetsController.php +++ b/src/Http/Controllers/CP/Assets/AssetsController.php @@ -124,7 +124,12 @@ public function store(Request $request) try { $validator->validate(); } catch (ValidationException $e) { - throw $e->status(409); + // The sanitized path can differ from the uploaded filename, so tell the uploader which asset exists. + return response()->json([ + 'message' => __('The given data was invalid.'), + 'errors' => $e->errors(), + 'existing' => $container->asset($path)->id(), + ], 409); } } diff --git a/tests/Feature/Assets/StoreAssetTest.php b/tests/Feature/Assets/StoreAssetTest.php index 96a4e79b0a6..4d389b897e1 100644 --- a/tests/Feature/Assets/StoreAssetTest.php +++ b/tests/Feature/Assets/StoreAssetTest.php @@ -134,7 +134,8 @@ public function it_doesnt_upload_when_file_exists_with_different_casing() 'file' => UploadedFile::fake()->image('tEsT.jpg'), ]) ->assertStatus(409) - ->assertInvalid(['path' => 'A file already exists with this name.']); + ->assertInvalid(['path' => 'A file already exists with this name.']) + ->assertJson(['message' => 'The given data was invalid.', 'existing' => 'test_container::path/to/test.jpg']); } #[Test]