Draft: feat(conflict): Add conflict resolution UI with viewport selection and route integration

[Description of changes]

Testing instructions

  1. Enable conflict UX
    ddev drush en canvas_dev_mode -y && ddev drush cr
    Expected: conflict notifications and conflict resolution UI are enabled.
  2. Create one conflict
    Open Canvas page 2, make a small edit, wait for autosave, then run:
    ddev drush esav canvas_page 2 -y
    Expected:
    • Conflict toast appears with Resolve conflicts.
    • Review changes shows 1 conflict to resolve.
    • Conflicted row is red with warning icon.
    • Checkbox is disabled.
    • Row menu shows Resolve conflict.
  3. Open conflict resolver
    Click toast action, banner button, or row menu Resolve conflict.
    Expected:
    • Conflict page opens.
    • Published version and New version are shown side by side.
    • Date appears like Updated M/D/YY at H:MM AM/PM.
    • Resolve conflict is disabled until a version is selected.
    • Visual/Text/Props tabs and viewport controls work.
  4. Verify pagination with two conflicts
    Create another conflict on page 1 using the same edit + ddev drush esav canvas_page 1 -y flow.
    Expected:
    • Banner shows 2 conflicts to resolve.
    • Resolver footer shows Review 1 of 2.
    • Next / Previous navigation works.
    • Selected version resets when moving to another conflict.
  5. Resolve with Published version
    Select Published version, then click Resolve conflict.
    Expected:
    • Autosave/user changes for that entity are discarded.
    • Conflict row disappears from pending changes.
  6. Resolve with New version
    Open another conflict, select New version, then click Resolve conflict.
    Expected:
    • Conflict is cleared.
    • Change remains as a normal selectable pending change.
    • It can be selected and published.
  7. Verify dev mode disabled
    ddev drush pm:uninstall canvas_dev_mode -y && ddev drush cr
    Expected:
    • Conflict toast/bell UI is hidden.
    • Conflict banner/red row styling is hidden.
    • Conflict-specific checkbox blocking is not applied.
    • /canvas/conflict redirects back to editor.
  8. Cleanup
    ddev drush ev "\Drupal::keyValue('canvas.auto_save')->deleteAll();" && ddev drush cr
    Expected:
    • No pending conflicts remain after refresh/polling.
    • Conflict banner and notifications disappear.

Closes #3591601

Merge request reports

Loading