[6.x] New Asset Exists Modal Resolution Feature#14433
[6.x] New Asset Exists Modal Resolution Feature#14433jackmcdade wants to merge 12 commits into6.xfrom
Conversation
Works with uploading and moving assets. Resolves #14381.
This updates the asset conflict UX by making modal-dismiss behavior resolve as cancel, only showing “apply to all” when multiple upload conflicts exist, and replacing recursive move-conflict continuation with an iterative loop. It also adds MoveAsset tests for non-conflicting moves, same-folder no-op moves, and explicit cancel strategy handling.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 561b096. Configure here.
| actionFailed(response = {}) { | ||
| this.$toast.error(response.message || __('Action failed')); | ||
| this.$refs.listing.refresh(); | ||
| }, |
There was a problem hiding this comment.
New actionFailed duplicates existing actionCompleted failure path
Low Severity
The new actionFailed method is functionally identical to calling actionCompleted(false, response). Both show an error toast with response.message || __('Action failed') and call this.$refs.listing.refresh(). continueMoveConflictResolution uses actionFailed in three places where actionCompleted(false, response) would produce the exact same behavior, introducing a redundant code path that diverges from the standard pattern.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 561b096. Configure here.
|
|
||
| if ($index > 0) { | ||
| $filename .= '-'.$index; | ||
| } |
There was a problem hiding this comment.
Timestamp index suffix skips zero for first conflicting asset
Low Severity
The timestamp strategy uses $index > 0 from the outer foreach to decide whether to append an index suffix, but $index is the position in the full $assets collection, not relative to conflicting assets. If the first batch asset doesn't conflict but the second does (at $index = 1), it still gets a -1 suffix. Meanwhile, a single conflicting asset sent from the frontend's per-asset resolution always has $index = 0 and never gets a suffix. While moveUnique prevents actual collisions, the logic is misleading—it conflates "first item in the collection" with "doesn't need a disambiguation suffix."
Reviewed by Cursor Bugbot for commit 561b096. Configure here.


Works with uploading and moving assets. Resolves #14381.
asset-conflicts.mp4
Note
Medium Risk
Changes asset upload and move flows to return/handle conflict metadata and apply overwrite/keep-both policies, which affects file operations and cache invalidation. Risk is moderate due to new client-side state machines/queues and backend conflict handling paths.
Overview
Adds first-class asset conflict resolution for both uploading and moving files, replacing the per-upload dropdown UI with centralized modals that offer Cancel, Keep Both (timestamp), and Overwrite, with optional apply-to-all behavior.
Backend now surfaces structured conflict details for uploads (409 response includes
conflictpayload) and moves (MoveAssetdetects destination collisions and either resolves via strategy or throwsAssetConflictExceptioncaptured byActionControllerto return conflict context andcompleted_moves). The move logic also clears Glide caches on overwrite andAsset::move()now forgets the old meta cache key.Uploader/browser wiring was updated to support bulk drag-move selections, queue multiple upload conflicts, continue move operations across multiple selections with ID remapping, and bust/reload image caches after overwrite/timestamp resolutions; tests were added/updated to cover move conflict strategies and Glide cache clearing on upload.
Reviewed by Cursor Bugbot for commit 561b096. Bugbot is set up for automated code reviews on this repo. Configure here.