-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Move/Duplicate: Add early validation for content type and structure constraints (closes #20451) #21158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
… modal open in case the backend should fail the validation
…error in footer - Add name property to move-to and duplicate-to modal tokens - Display item name in modal headline using moveOrCopy_moveTo and moveOrCopy_copyTo localization keys - Move validation error messages to modal footer (actions slot) for better visibility - Update localization strings to use cleaner format with quotes around item name - Pass name from document and media actions to modals - Fix incorrect localization key in document duplicate modal 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
When move/duplicate validation fails due to content type restrictions, all other items of that same content type are now automatically disabled in the tree picker. This prevents users from trying multiple destinations of the same type that will all fail for the same reason. Applied to single actions (document move, media move, document duplicate) and bulk actions (document bulk move, document bulk duplicate, media bulk move). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add align-items: center to footer-layout actions to prevent buttons from stretching when error messages wrap to multiple lines - Add padding to error messages so they don't touch the border 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add validation to move actions to prevent: - Moving a document to one of its descendants (would create circular reference) - Moving a document to its current parent (no-op) For documents, the ancestors array on tree items enables descendant detection. For media, descendant detection relies on backend validation as tree items don't include ancestors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Show "X items" in the modal headline for bulk operations so users know how many items they're moving/duplicating. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements comprehensive early validation for Move and Duplicate operations in the Umbraco CMS backoffice, providing immediate feedback when users select invalid destinations based on content type constraints. The implementation shifts from generic "moveTo" and "duplicateTo" action kinds to custom implementations with validation logic, introduces new modal components with error handling, and adds localization support.
Key Changes:
- Replaces generic action kinds with custom implementations that perform real-time content type validation
- Introduces three new modal components (move-to, duplicate-to variants) with validation callbacks and dynamic tree filtering
- Implements lazy validation that disables invalid destination types after they're selected
- Adds descendant prevention for move operations and current-parent prevention
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| move-document.action.ts | New custom implementation for single document move with content type validation and descendant/parent filtering |
| move-document-bulk.action.ts | New bulk document move action with multi-item validation and error listing |
| move-media.action.ts | New custom implementation for single media move with content type validation |
| move-media-bulk.action.ts | New bulk media move action with multi-item validation |
| duplicate-document.action.ts | Enhanced duplicate action with content type validation via callbacks |
| duplicate-document-bulk.action.ts | New bulk duplicate action with multi-item validation |
| move-to-modal.element.ts | New modal component with validation callbacks, dynamic filtering, and error display |
| duplicate-to-modal.element.ts | New modal component for generic duplicate-to operations with validation support |
| duplicate-document-modal.element.ts | Enhanced duplicate modal with validation callbacks and error handling |
| move-to-modal.token.ts | New type definitions for move modal data, including callback interfaces |
| duplicate-to-modal.token.ts | Enhanced type definitions for duplicate modal with validation callbacks |
| duplicate-document-modal.token.ts | Enhanced type definitions with validation and submit callbacks |
| move-to.action.ts | Updated generic move action to use new modal and submit callbacks |
| duplicate-to.action.ts | Updated generic duplicate action to use callbacks and improved error handling |
| manifests.ts (documents/media) | Changed from generic "moveTo"/"duplicateTo" kinds to "default" kind with custom API imports |
| footer-layout.element.ts | Added flexbox alignment to center error messages with buttons |
| en.ts / da.ts | Updated localization strings to use dynamic item names in modal headlines |
| commands.md | Added quick verification commands for development workflow |
...eb.UI.Client/src/packages/documents/documents/entity-actions/move-to/move-document.action.ts
Outdated
Show resolved
Hide resolved
...lient/src/packages/core/tree/entity-actions/duplicate-to/modal/duplicate-to-modal.element.ts
Outdated
Show resolved
Hide resolved
...kages/documents/documents/entity-actions/duplicate/modal/duplicate-document-modal.element.ts
Outdated
Show resolved
Hide resolved
...nt/src/packages/documents/documents/entity-bulk-actions/move-to/move-document-bulk.action.ts
Show resolved
Hide resolved
...lient/src/packages/documents/documents/entity-actions/duplicate/duplicate-document.action.ts
Show resolved
Hide resolved
src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/move-to/move-media.action.ts
Show resolved
Hide resolved
...raco.Web.UI.Client/src/packages/core/tree/entity-actions/move/modal/move-to-modal.element.ts
Show resolved
Hide resolved
...Web.UI.Client/src/packages/media/media/entity-bulk-actions/move-to/move-media-bulk.action.ts
Show resolved
Hide resolved
...raco.Web.UI.Client/src/packages/core/tree/entity-actions/move/modal/move-to-modal.element.ts
Show resolved
Hide resolved
...kages/documents/documents/entity-bulk-actions/duplicate-to/duplicate-document-bulk.action.ts
Show resolved
Hide resolved
The action's pickableFilter closure already manages disabled state via #disallowedDocumentTypes. The modal now just passes the filter through directly instead of maintaining its own _disabledItems Set.
…ions - Add fallback to unique when variant name is missing in move-document.action.ts - Add fallback to unique when variant name is missing in duplicate-document.action.ts - Add comment clarifying that duplicating to descendants is intentionally allowed (unlike move) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Summary
Closes #20451
This PR implements early validation for Move and Duplicate operations in the backoffice, providing immediate feedback to users when selecting invalid destinations.
Addressing #20451 - Different Approach
The original issue suggested that invalid destinations should not be selectable at all. We took a lazy validation approach instead, for good reasons:
Why not pre-disable all invalid items?
Our approach: Validate on selection
This gives users immediate feedback without the performance cost of pre-computing all valid destinations.
Features Added
Screenshots
Move Modal - Initial State
Shows item name in headline ("Select where Home should be moved to below"):
Move Modal - Descendants Disabled
All descendants of the source item are automatically disabled (greyed out):

Move Modal - Content Type Error
Error shown when selecting a destination that doesn't allow the source's document type:

Move Modal - Valid Selection
Submit button enabled when a valid destination is selected:

Duplicate Modal - Content Type Error
Same validation for duplicate operations:

Design Notes
Why similar modal code is intentional
The modals for different entity types (documents, media, etc.) have similar but separate implementations. This follows Umbraco's package architecture:
The validation logic (e.g.,
onTreeSelectionChange) is similar across modals but not identical, and the cost of maintaining a few similar methods is lower than the coupling a shared abstraction would introduce.Why duplicating to descendants is allowed
Unlike move operations, duplicating a document to one of its descendants is intentionally allowed - it creates a copy without circular reference issues.
Test Plan
🤖 Generated with Claude Code