Review of changes and Conflict resolution
Migrated issue
Reported by: f.mazeikis
Was manually converted to a milestone on June 19, 2026, from [META] Review of changes and Conflict resolution (#3587587 - closed).
Overview
This is a meta to track work to add ability to add the following:
- Add conflict detection when underlying entity that auto-save entry has been based on is updated outside of Canvas UI
- Add ability to detect and resolve such conflicts using Canvas UI
- Build UI that allows to use side-by-side comparison when resolving such conflict
- Ability to conveniently Review changes to multiple entities re-using much of the same new UI
Refer to child issues for actionable steps.
🟢 Description and requirements:🟢 Proposed resolution:🟡 ADR🟢 Designs🚧 🏗️ Related issues🚫 Out of Scope
Current problems
- Users reviewing changes in their autosave before publishing are unaware if the published content has been updated externally, risking silent overwrites of concurrent work.
- When concurrent changes occur between the updated entity a user has in their autosave and the published version of the same entity a user started with, users lack visibility into the conflicting versions.
- Relying on the “preview” functionality for individual entities in Canvas UI is insufficient when reviewing changes in autosave, as there is no comparison to currently published versions of entities.
- Users don't have a quick and convenient way to visually review changes made to multiple entities.
Proposed resolution
Product Speak:
Expected outcome from a Product POV, by @lauriii:
We should create clear, visual interface to identify and resolve version conflicts before publishing. By flagging conflicts in the review panel and providing a side-by-side comparison modal per entity, users can confidently select the correct version to proceed with, preventing accidental overwrites. Same functionality can also be used to preview any non-conflicting changes vs the published version of the entity.
User journeys:
Original user journeys written by @lauriii, expanded and clarified with the help of @mark-dodgson:
Conflict Identification
Given a user has an un-published autosave changes on an entity in Canvas
And that the same entity has been updated and saved before user published their changes
When the user clicks "Review Changes" to publish
Then the specific entity is visibly flagged with a "Conflict" indicator in the review panel and cannot be selected for publishing
And a dedicated "Conflict resolution CTA" section appears in "Review Changes" panel above the list of entities with changes.
Conflict Resolution Preview Access
Given the user is viewing the "Review Changes" panel and there are auto-save entries with detected conflicts
When the user clicks on the "Resolve X conflicts" button in the "Conflict resolution CTA" section above the list of un-published entities in the "Review Changes" panel
Then the "Conflict resolution UI" opens and it contains the list of all detected conflicts in the order they appear in "Review Changes"
And this UI has controls that allow the user to navigate between the conflicts, view them in side-by-side comparison and resolve each one individually.
Conflict Resolution Access via contextual menu
Given the user is viewing the "Review Changes" panel when conflicts are detected
When the user chooses an entity with a conflict and clicks on "Resolve Conflict" option in the contextual menu this entity entity
Then the "Conflict resolution UI" opens starting the list with the entity chosen by the user
And the rest of the entities with conflicts in the "Conflict resolution UI" list are ordered as they appear in "Review changes" panel.
Conflict Resolution Selection
Given the user is viewing the side-by-side comparison of a an entity with detected conflict in the "Conflict resolution UI"
When the user is prompted to resolve the conflict
Then the user must be presented with two distinct, mutually exclusive options: "Keep Published Version" or "Keep Autosaved Version".
Executing the resolution
Given the user has selected one of the versions in the conflict resolution modal
When the user confirms their selection
Then the conflict is resolved immediately for this and other users in Canvas Ui.
Expected conflict resolution ui behavior
Given the user is using conflict resolution UI
When resolves a conflict
Then Canvas UI is updated immediately to reflect the users action
And all counts of conflicts in Canvas UI are updated
And the entity is no longer marked as having a conflict.
Resolving the conflict by choosing the Autosaved version
Given the user has selected the Autosaved of the version in the conflict resolution modal
When the user confirms their selection by clicking "Resolve Conflict" button in the "Conflict resolution UI"
Then the changes in the Published version are ignored
And the conflict indicator is removed from the "Review Changes" panel for this entity
And the entity can be selected for publishing in the "Review Changes" panel
And the user can publish the changes made to this entity.
Resolving the conflict by choosing the Published version
Given the user has selected one the Published version in the conflict resolution modal
When the user confirms their selection by clicking "Resolve Conflict" button in the "Conflict resolution UI"
Then user made changes to this entity in Canvas are discarded
And the entity is removed from the "Review changes" list
And there are no changes to publish for this entity in Canvas UI.
Side-by-Side Preview Access
Given the user is viewing the "Review Changes" panel
When the user clicks on the "Review selected changes" link at the bottom of "Review Changes" panel
Then a new Canvas UI element opens displaying a side-by-side comparison of the published version and the autosaved version of the first entity selected for publishing
And all the other entities with changes that are selected for publishing are also available for preview in this new UI.
And the Page entities appear in the same order as they appear in the "Review Changes" panel.
Side-by-Side Preview UI navigation
Given the user opens the new Canvas side-by-side review UI panel
When the user wants to review another entity using this UI
Then they can use the pagination in the left bottom corner to see how many entities are available for preview and which entity number they are on
And they can use "previous" and "next" navigation controls of the new "side-by-side review UI" to move between all Page entities with changes selected for publishing.
Side-by-Side Preview Access via contextual menu
Given the user is viewing the "Review Changes" panel
When the user clicks on contextual menu option "Review Changes" of a specific entity selected for publishing
Then a new Canvas UI element opens displaying a side-by-side comparison of the entity user clicked selected via the contextual menu
And this entity is set to be the first item in the pagination of the new side-by-side UI panel
And this new Canvas UI element has controls that allow user to navigate between the entities selected for publishing and view them in side-by-side comparison
And all the rest of Page entities selected for publishing appear in the in the pagination of the new side-by-side UI panel using same order as they appear in the "Review Changes" panel.
Additional criteria:
- A conflict in Canvas can occur by any means of updating the underlying entity that Canvas user has updated in their autosave. This includes (but is not limited to) config and content import, CLI commands, editing and saving of the entity by another user via Drupal UI or code.
- If user resolves a conflict in favour of published entity version, then the entry for that entity is removed from the autosave, resulting in nothing to save or publish until user edits that entity again.
- If a user resolves a conflict in the Canvas UI in favour of entity version in autosave:
- If the user continues making changes to an entity with a "conflict resolved" flag in autosave via the Canvas UI, their actions will not trigger a new "conflict detection" flag
- After "conflict resolved" flag is added to an entity in autosave, only further changes to published version of the entity can trigger new "conflict detected" flag
- If a user resolves conflict in the Canvas UI in favour of entity version in autosave, we should track which specific entity and specific conflict has been resolved, in case additional conflicts occur after resolving the initial conflict
- If Canvas will be integrated with Workspaces, the expectation is for conflict resolution to continue work as is in the FE part of Canvas and BE part of Canvas should use entity revision id changes for “Conflict detection”
- When user opens a modal with side by side visual comparison there should be UI element that allows the comparison modal to be expanded to fill the viewport
- Visual side-by-side comparison of changes should work on all screen sizes supported by Canvas
- Visual side-by-side comparison should be reasonably fast when loading side by side comparisons
- Visual side-by-side comparison must be able successfully render visual comparisons of complex pages with deep component trees.
- Entities that can't be meaningfully compared using visual representations should be compared using their text-based representations (for example - global CSS entity)
Canvas Engineering Speak
Current conflict detection
We have added rudimentary conflict detection as part of and .
In #3490565 we put in logic to throw an exception if client didn't send the latest auto-save hash for the entity and regions. This prevents 2 users for editing at the same time and wiping out each others changes.
In we expanded this functionality further and added support in Canvas UI enforcing "Canvas does not support concurrent editing" by forcing Canvas users to refresh their page when a conflict in autosave is detected.
This does not cover changes to entity that occur due to entity update and save outside of Canvas UI. For example, if user opens Canvas UI and starts editing "Full content template" for the "Article" content type.
What entity changes are needed to detect a conflict:
- Canvas Page (content entity): any change (including a change in the revision ID) is considered to be a conflict. The only exception is the
changedfield - updating it without updating any other field values (including revision id) will not be detected as a conflict. - Content Template, Code Component, Region, Pattern (config entities): the hash of all entity properties will be used to detect changes. The only fields exempt from the hash are:
statusandlabelproperties.
The broad plan:
- Start small - Canvas Page support as MvP, extend to all the other entity types later
- Text-based side-by-side comparison will use JS library with pretty diff
- Visual side-by-side will use modified Canvas preview endpoint
- Visual comparison will only be available for entity types where it makes sense - Pages, Templates, etc. Entities with no meaningful visual preview (global CSS
🤨 ) will only use text-based comparison - Don't break existing conflict detection, only expand, improve and bugfix where required
- Reuse currently existing infrastructure that is proven to work (like preview endpoint)
- Reuse conflict resolution UI to allow reviews of all entities with changes selected for publishing
The detailed plan:
- Make minor
auto-save/pendingrefactor to encapsulate the auto-save entries in a top leveldataproperty. - Add logic to detect and store conflicts that can be resolved in the new UI:
- Changes in
AutoSaveManagerand associated tests - Start storing
original_hashon auto-save entry save, that way we can tell if underlying entity has been updated. Do not sendoriginal_hashto client side - Start detecting, storing and updating
conflictproperty on auto-save entry save. Only send it client side if the conflict is active and only in the relevant `errors` item
- Changes in
- Add HTTP 409 response definition for
auto-save/pendingendpoint to openapi.yml:- Use
errorsat the top level to mark which entities contain conflicts - In the
errorsadd items for each entity with the detected conflict. Mark items we can resolve in UI with new error code and usemetaproperty of the error item to store theconflictobject - The
conflictobject should have theconflictId,statusandtimestampproperties - HTTP 409 response should return both
dataanderrorsproperties, so client side could know which entities have active conflicts
- Use
- Make
auto-save/pendingcontroller return HTTP 409 if any active conflicts are found in the list of entries to be returned - Make sure entity cache tags from auto-save entries are used in caching of the
auto-save/pendingresponse - Return both
dataanderrorsproperties on HTTP 409, so client side could know which entities have conflicts - Extend these changes to publishing and ?? endpoints:
- Validation during autosave publishing should compare revision ids and a hashes and prevent publishing if a conflict is detected and not previously marked as resolved
- If any unresolved conflicts are detected during publishing, the autosave should be updated with flags identifying entities with unresolved conflicts
- Add an ability to resolve a conflict via HTTP PATCH call to the auto-save API endpoint (or a new dedicated endpoint) with the conflict id and status
- Modify preview endpoint to accept argument that will allow endpoint to return current auto-save version of the preview (default option) or the published version of this entity
- Add new Canvas endpoint for text-based previews:
- Config export and default content export representations of entities should be used
- Both published and auto-save entity per request or two separate requests
- Argument listing properties or a dedicated route with hardcoded entity type to property map can be used to filter text-based representation to a subset of fields/properties (for example - "only input values" or "only JS code")
- Text-based comparison will be available to most (if not all) entity types and will be based on default content export representations for content entities and config export versions of config entities
- For some entity types only a subset of their properties could be displayed in text-based side-by-side (
Codetab for code components and global css) + full text-based representation in a separate tab
- Emit notifications in the BE on conflict detection (figure out how to only do it once per detected conflict too) with "action" that allows client side to open conflict resolution UI.
- Have fun along the way
User interface changes
- "Review changes" dropdown in the Canvas UI should display conflicts when they are detected
- New "Visual comparison UI" that allows user to view a side by side comparison of the of updated entity in autosave versus the published version of same entity
- New "Conflict resolution UI" that shows side by side comparison of updated entity in autosave versus the conflicting published entity. This UI should have controls that allow user to select one version, which results in discarding the other
- "Review changes" dropdown in the Canvas UI should have a mechanism to open a modal (or similar) that would contain "Conflict resolution UI" for entities with detected conflicts
- "Review changes" dropdown in the Canvas UI should have a mechanism to open a modal (or similar) that would contain "Visual comparison UI" for updated entities
🛑 ADR
Work in progress
🟢 Designs
All designs made by @mark-dodgson and exported as PNGs from Figma.
Conflict resolution
- Toast notification with a detected conflict:
- Conflict detected CTA and marked entities in the "Review changes" panel:
- Conflict resolution UI with side-by-side visual comparison:
- Conflict resolution UI when no active conflicts detected:
Review of changes
- New link at the bottom of "Review changes" panel:
- New "Review changes" UI using visual entity representation for side-by-side comparison of the published entity version with the version user has in Canvas auto-save:
- New "Review changes" UI using text-based entity representation for side-by-side comparison:
🚧 🏗️ Related issues
- [#3520592][PP-1] Do not allow a user Publish request while there are pending changes to the current layout - currently describes a bug that still needs be fixed. This (#3587587 (closed)) issue helps resolving conflicts and adds visual comparison, but fixing #3520592 would fix a bug causing incorrect conflict detection.
- [#3532056]For less conflict errors only validate region auto-save on layout PATCH - should still be fixed. It will reduce the amount of conflicts that can occur, but won't solve the problem entirely and this issue will only make it easier to handle the conflicts.
- [#3492065]Enable concurrent editing: Replace the postPreview action with atomic equivalents - should definitely still be implemented. It would add groundwork for implementing concurrent editing for multiple Canvas users. This (#3587587 (closed)) issue intentionally keeps concurrent changes to the same autosave entry out of scope. Me and @bnjmnm think both this (#3587587 (closed)) and #3492065 issues should work fairly well together as they solve related, but different problems. Some refactor or updates might be required, depending on which issue gets finished and merged first.
‼️ This issue does not make any of the related issues irrelevant or supersedes them ‼️
🚫 Out of scope
- Concurrent editing - "Conflict free concurrent editing" described in [#3492059] or any other changes related to concurrent editing of entities in Canvas UI by multiple users is out of scope for this issue.
- Pre-existring "rudimentary conflict detection" - will continue to work as is:
- Fine-grained conflict detection - current implementation of conflict detection does not force the user to refresh the page if the following fields or properties are modified:
changedfield on for Canvas Page entities (or any other entities implementingEntityChangedInterface)statusandlabelproperties of Canvas config entities
This will continue to work as is, but will not be expanded to include any additional fields.
- Updating the version of the entity in the autosave with changes to it's data fields when possible - Currently If config entity is saved with label and/or status property updates, these values will also be updated in it's respective autosave entry, if one exists. This will continue working as is. Expanding this functionality to other fields or properties will require careful consideration and is out of scope for this ticket.
Related issue: Issue #3520592
Related issue: Issue #3532056
Related issue: Issue #3492059
Related issue: Issue #3492065
Related issue: Issue #3553775
Related issue: Issue #3586600







